Cleanup comments and internal variables (#4205)

This commit is contained in:
dubiousjim 2020-03-02 10:19:42 -05:00 committed by GitHub
parent 809019dc6e
commit 6cd46fa3ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 681 additions and 572 deletions

View file

@ -10,12 +10,11 @@ use rand;
use rand::Rng; use rand::Rng;
use walkdir::WalkDir; use walkdir::WalkDir;
#[cfg(unix)]
use std::os::unix::fs::{DirBuilderExt, PermissionsExt};
#[cfg(unix)] #[cfg(unix)]
use nix::unistd::{chown as unix_chown, Gid, Uid}; use nix::unistd::{chown as unix_chown, Gid, Uid};
#[cfg(any(unix))]
use std::os::unix::fs::DirBuilderExt;
#[cfg(any(unix))]
use std::os::unix::fs::PermissionsExt;
pub fn write_file<T: AsRef<[u8]>>( pub fn write_file<T: AsRef<[u8]>>(
filename: &Path, filename: &Path,
@ -48,12 +47,13 @@ pub fn write_file_2<T: AsRef<[u8]>>(
file.write_all(data.as_ref()) file.write_all(data.as_ref())
} }
#[cfg(any(unix))] #[cfg(unix)]
fn set_permissions(file: &mut File, perm: u32) -> std::io::Result<()> { fn set_permissions(file: &mut File, perm: u32) -> std::io::Result<()> {
debug!("set file perm to {}", perm); debug!("set file perm to {}", perm);
file.set_permissions(PermissionsExt::from_mode(perm & 0o777)) file.set_permissions(PermissionsExt::from_mode(perm & 0o777))
} }
#[cfg(not(any(unix)))]
#[cfg(not(unix))]
fn set_permissions(_file: &mut File, _perm: u32) -> std::io::Result<()> { fn set_permissions(_file: &mut File, _perm: u32) -> std::io::Result<()> {
// NOOP on windows // NOOP on windows
Ok(()) Ok(())
@ -102,13 +102,13 @@ pub fn mkdir(path: &Path, perm: u32, recursive: bool) -> std::io::Result<()> {
builder.create(path) builder.create(path)
} }
#[cfg(any(unix))] #[cfg(unix)]
fn set_dir_permission(builder: &mut DirBuilder, perm: u32) { fn set_dir_permission(builder: &mut DirBuilder, perm: u32) {
debug!("set dir perm to {}", perm); debug!("set dir perm to {}", perm);
builder.mode(perm & 0o777); builder.mode(perm & 0o777);
} }
#[cfg(not(any(unix)))] #[cfg(not(unix))]
fn set_dir_permission(_builder: &mut DirBuilder, _perm: u32) { fn set_dir_permission(_builder: &mut DirBuilder, _perm: u32) {
// NOOP on windows // NOOP on windows
} }
@ -123,11 +123,11 @@ pub fn chown(path: &str, uid: u32, gid: u32) -> Result<(), ErrBox> {
#[cfg(not(unix))] #[cfg(not(unix))]
pub fn chown(_path: &str, _uid: u32, _gid: u32) -> Result<(), ErrBox> { pub fn chown(_path: &str, _uid: u32, _gid: u32) -> Result<(), ErrBox> {
// Noop // FAIL on Windows
// TODO: implement chown for Windows // TODO: implement chown for Windows
let e = std::io::Error::new( let e = std::io::Error::new(
std::io::ErrorKind::Other, std::io::ErrorKind::Other,
"Op not implemented".to_string(), "Not implemented".to_string(),
); );
Err(ErrBox::from(e)) Err(ErrBox::from(e))
} }

View file

@ -1,19 +1,22 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync, sendAsync } from "./dispatch_json.ts"; import { sendSync, sendAsync } from "./dispatch_json.ts";
/** Changes the permission of a specific file/directory of specified path /** Synchronously changes the permission of a specific file/directory of
* synchronously. * specified path. Ignores the process's umask.
* *
* Deno.chmodSync("/path/to/file", 0o666); * Deno.chmodSync("/path/to/file", 0o666);
*/ *
* Requires `allow-write` permission. */
export function chmodSync(path: string, mode: number): void { export function chmodSync(path: string, mode: number): void {
sendSync("op_chmod", { path, mode }); sendSync("op_chmod", { path, mode });
} }
/** Changes the permission of a specific file/directory of specified path. /** Changes the permission of a specific file/directory of specified path.
* Ignores the process's umask.
* *
* await Deno.chmod("/path/to/file", 0o666); * await Deno.chmod("/path/to/file", 0o666);
*/ *
* Requires `allow-write` permission. */
export async function chmod(path: string, mode: number): Promise<void> { export async function chmod(path: string, mode: number): Promise<void> {
await sendAsync("op_chmod", { path, mode }); await sendAsync("op_chmod", { path, mode });
} }

View file

@ -1,8 +1,11 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync, sendAsync } from "./dispatch_json.ts"; import { sendSync, sendAsync } from "./dispatch_json.ts";
/** /** Synchronously change owner of a regular file or directory. Linux/Mac OS
* Change owner of a regular file or directory synchronously. Unix only at the moment. * only at the moment.
*
* Requires `allow-write` permission.
*
* @param path path to the file * @param path path to the file
* @param uid user id of the new owner * @param uid user id of the new owner
* @param gid group id of the new owner * @param gid group id of the new owner
@ -11,8 +14,11 @@ export function chownSync(path: string, uid: number, gid: number): void {
sendSync("op_chown", { path, uid, gid }); sendSync("op_chown", { path, uid, gid });
} }
/** /** Change owner of a regular file or directory. Linux/Mac OS only at the
* Change owner of a regular file or directory asynchronously. Unix only at the moment. * moment.
*
* Requires `allow-write` permission.
*
* @param path path to the file * @param path path to the file
* @param uid user id of the new owner * @param uid user id of the new owner
* @param gid group id of the new owner * @param gid group id of the new owner

View file

@ -1,29 +1,29 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync, sendAsync } from "./dispatch_json.ts"; import { sendSync, sendAsync } from "./dispatch_json.ts";
/** Copies the contents of a file to another by name synchronously. /** Synchronously copies the contents and permissions of one file to another
* Creates a new file if target does not exists, and if target exists, * specified path, by default creating a new file if needed, else overwriting.
* overwrites original content of the target file. * Fails if target path is a directory or is unwritable.
*
* It would also copy the permission of the original file
* to the destination.
* *
* Deno.copyFileSync("from.txt", "to.txt"); * Deno.copyFileSync("from.txt", "to.txt");
*/ *
export function copyFileSync(from: string, to: string): void { * Requires `allow-read` permission on fromPath.
sendSync("op_copy_file", { from, to }); * Requires `allow-write` permission on toPath. */
export function copyFileSync(fromPath: string, toPath: string): void {
sendSync("op_copy_file", { from: fromPath, to: toPath });
} }
/** Copies the contents of a file to another by name. /** Copies the contents and permissions of one file to another specified path,
* * by default creating a new file if needed, else overwriting. Fails if target
* Creates a new file if target does not exists, and if target exists, * path is a directory or is unwritable.
* overwrites original content of the target file.
*
* It would also copy the permission of the original file
* to the destination.
* *
* await Deno.copyFile("from.txt", "to.txt"); * await Deno.copyFile("from.txt", "to.txt");
*/ *
export async function copyFile(from: string, to: string): Promise<void> { * Requires `allow-read` permission on fromPath.
await sendAsync("op_copy_file", { from, to }); * Requires `allow-write` permission on toPath. */
export async function copyFile(
fromPath: string,
toPath: string
): Promise<void> {
await sendAsync("op_copy_file", { from: fromPath, to: toPath });
} }

View file

@ -2,19 +2,25 @@
import { sendSync } from "./dispatch_json.ts"; import { sendSync } from "./dispatch_json.ts";
/** /**
* `cwd()` Return a string representing the current working directory. * **UNSTABLE**: maybe needs permissions.
* If the current directory can be reached via multiple paths *
* (due to symbolic links), `cwd()` may return * Return a string representing the current working directory.
* any one of them. *
* throws `NotFound` exception if directory not available * If the current directory can be reached via multiple paths (due to symbolic
* links), `cwd()` may return any one of them.
*
* Throws `Deno.errors.NotFound` if directory not available.
*/ */
export function cwd(): string { export function cwd(): string {
return sendSync("op_cwd"); return sendSync("op_cwd");
} }
/** /**
* `chdir()` Change the current working directory to path. * **UNSTABLE**: maybe needs permissions.
* throws `NotFound` exception if directory not available *
* Change the current working directory to the specified path.
*
* Throws `Deno.errors.NotFound` if directory not available.
*/ */
export function chdir(directory: string): void { export function chdir(directory: string): void {
sendSync("op_chdir", { directory }); sendSync("op_chdir", { directory });

View file

@ -3,72 +3,69 @@ import { StatResponse } from "./stat.ts";
import { build } from "./build.ts"; import { build } from "./build.ts";
/** A FileInfo describes a file and is returned by `stat`, `lstat`, /** A FileInfo describes a file and is returned by `stat`, `lstat`,
* `statSync`, `lstatSync`. * `statSync`, `lstatSync`. A list of FileInfo is returned by `readDir`,
*/ * `readDirSync`. */
export interface FileInfo { export interface FileInfo {
/** The size of the file, in bytes. */ /** The size of the file, in bytes. */
len: number; len: number;
/** The last modification time of the file. This corresponds to the `mtime` /** The last modification time of the file. This corresponds to the `mtime`
* field from `stat` on Unix and `ftLastWriteTime` on Windows. This may not * field from `stat` on Linux/Mac OS and `ftLastWriteTime` on Windows. This
* be available on all platforms. * may not be available on all platforms. */
*/
modified: number | null; modified: number | null;
/** The last access time of the file. This corresponds to the `atime` /** The last access time of the file. This corresponds to the `atime`
* field from `stat` on Unix and `ftLastAccessTime` on Windows. This may not * field from `stat` on Unix and `ftLastAccessTime` on Windows. This may not
* be available on all platforms. * be available on all platforms. */
*/
accessed: number | null; accessed: number | null;
/** The last access time of the file. This corresponds to the `birthtime` /** The last access time of the file. This corresponds to the `birthtime`
* field from `stat` on Unix and `ftCreationTime` on Windows. This may not * field from `stat` on Mac/BSD and `ftCreationTime` on Windows. This may not
* be available on all platforms. * be available on all platforms. */
*/
created: number | null; created: number | null;
/** The file or directory name. */ /** The file or directory name. */
name: string | null; name: string | null;
/** ID of the device containing the file.
/** ID of the device containing the file. Unix only. */ *
* _Linux/Mac OS only._ */
dev: number | null; dev: number | null;
/** Inode number.
/** Inode number. Unix only. */ *
* _Linux/Mac OS only._ */
ino: number | null; ino: number | null;
/** The underlying raw st_mode bits that contain the standard Unix permissions /** The underlying raw st_mode bits that contain the standard Unix permissions
* for this file/directory. TODO Match behavior with Go on windows for mode. * for this file/directory. TODO Match behavior with Go on windows for mode.
*/ */
mode: number | null; mode: number | null;
/** Number of hard links pointing to this file.
/** Number of hard links pointing to this file. Unix only. */ *
* _Linux/Mac OS only._ */
nlink: number | null; nlink: number | null;
/** User ID of the owner of this file.
/** User ID of the owner of this file. Unix only. */ *
* _Linux/Mac OS only._ */
uid: number | null; uid: number | null;
/** User ID of the owner of this file.
/** User ID of the owner of this file. Unix only. */ *
* _Linux/Mac OS only._ */
gid: number | null; gid: number | null;
/** Device ID of this file.
/** Device ID of this file. Unix only. */ *
* _Linux/Mac OS only._ */
rdev: number | null; rdev: number | null;
/** Blocksize for filesystem I/O.
/** Blocksize for filesystem I/O. Unix only. */ *
* _Linux/Mac OS only._ */
blksize: number | null; blksize: number | null;
/** Number of blocks allocated to the file, in 512-byte units.
/** Number of blocks allocated to the file, in 512-byte units. Unix only. */ *
* _Linux/Mac OS only._ */
blocks: number | null; blocks: number | null;
/** Returns whether this is info for a regular file. This result is mutually /** Returns whether this is info for a regular file. This result is mutually
* exclusive to `FileInfo.isDirectory` and `FileInfo.isSymlink`. * exclusive to `FileInfo.isDirectory` and `FileInfo.isSymlink`. */
*/
isFile(): boolean; isFile(): boolean;
/** Returns whether this is info for a regular directory. This result is /** Returns whether this is info for a regular directory. This result is
* mutually exclusive to `FileInfo.isFile` and `FileInfo.isSymlink`. * mutually exclusive to `FileInfo.isFile` and `FileInfo.isSymlink`. */
*/
isDirectory(): boolean; isDirectory(): boolean;
/** Returns whether this is info for a symlink. This result is /** Returns whether this is info for a symlink. This result is
* mutually exclusive to `FileInfo.isFile` and `FileInfo.isDirectory`. * mutually exclusive to `FileInfo.isFile` and `FileInfo.isDirectory`. */
*/
isSymlink(): boolean; isSymlink(): boolean;
} }

View file

@ -21,19 +21,23 @@ import { OPS_CACHE } from "./runtime.ts";
let OP_READ = -1; let OP_READ = -1;
let OP_WRITE = -1; let OP_WRITE = -1;
/** Open a file and return an instance of the `File` object /** Synchronously open a file and return an instance of the `File` object.
* synchronously.
* *
* const file = Deno.openSync("/foo/bar.txt", { read: true, write: true }); * const file = Deno.openSync("/foo/bar.txt", { read: true, write: true });
*
* Requires `allow-read` and `allow-write` permissions depending on mode.
*/ */
export function openSync(filename: string, capability?: OpenOptions): File; export function openSync(filename: string, mode?: OpenOptions): File;
/** Open a file and return an instance of the `File` object
* synchronously. /** Synchronously open a file and return an instance of the `File` object.
* *
* const file = Deno.openSync("/foo/bar.txt", "r"); * const file = Deno.openSync("/foo/bar.txt", "r");
*
* Requires `allow-read` and `allow-write` permissions depending on mode.
*/ */
export function openSync(filename: string, mode?: OpenMode): File; export function openSync(filename: string, mode?: OpenMode): File;
/**@internal*/
export function openSync( export function openSync(
filename: string, filename: string,
modeOrOptions: OpenOptions | OpenMode = "r" modeOrOptions: OpenOptions | OpenMode = "r"
@ -52,18 +56,22 @@ export function openSync(
return new File(rid); return new File(rid);
} }
/** Open a file and return an instance of the `File` object. /** Open a file and resolve to an instance of the `File` object.
* *
* const file = await Deno.open("/foo/bar.txt", { read: true, write: true }); * const file = await Deno.open("/foo/bar.txt", { read: true, write: true });
*
* Requires `allow-read` and `allow-write` permissions depending on mode.
*/ */
export async function open( export async function open(
filename: string, filename: string,
options?: OpenOptions options?: OpenOptions
): Promise<File>; ): Promise<File>;
/** Open a file and return an instance of the `File` object. /** Open a file and resolves to an instance of `Deno.File`.
* *
* const file = await Deno.open("/foo/bar.txt, "w+"); * const file = await Deno.open("/foo/bar.txt, "w+");
*
* Requires `allow-read` and `allow-write` permissions depending on mode.
*/ */
export async function open(filename: string, mode?: OpenMode): Promise<File>; export async function open(filename: string, mode?: OpenMode): Promise<File>;
@ -91,32 +99,35 @@ export async function open(
} }
/** Creates a file if none exists or truncates an existing file and returns /** Creates a file if none exists or truncates an existing file and returns
* an instance of the `File` object synchronously. * an instance of `Deno.File`.
* *
* const file = Deno.createSync("/foo/bar.txt"); * const file = Deno.createSync("/foo/bar.txt");
*
* Requires `allow-read` and `allow-write` permissions.
*/ */
export function createSync(filename: string): File { export function createSync(filename: string): File {
return openSync(filename, "w+"); return openSync(filename, "w+");
} }
/** Creates a file if none exists or truncates an existing file and returns /** Creates a file if none exists or truncates an existing file and resolves to
* an instance of the `File` object. * an instance of `Deno.File`.
* *
* const file = await Deno.create("/foo/bar.txt"); * const file = await Deno.create("/foo/bar.txt");
*
* Requires `allow-read` and `allow-write` permissions.
*/ */
export function create(filename: string): Promise<File> { export function create(filename: string): Promise<File> {
return open(filename, "w+"); return open(filename, "w+");
} }
/** Read synchronously from a file ID into an array buffer. /** Synchronously read from a file ID into an array buffer.
* *
* Return `number | EOF` for the operation. * Returns `number | EOF` for the operation.
* *
* const file = Deno.openSync("/foo/bar.txt"); * const file = Deno.openSync("/foo/bar.txt");
* const buf = new Uint8Array(100); * const buf = new Uint8Array(100);
* const nread = Deno.readSync(file.rid, buf); * const nread = Deno.readSync(file.rid, buf);
* const text = new TextDecoder().decode(buf); * const text = new TextDecoder().decode(buf);
*
*/ */
export function readSync(rid: number, p: Uint8Array): number | EOF { export function readSync(rid: number, p: Uint8Array): number | EOF {
if (p.length == 0) { if (p.length == 0) {
@ -135,9 +146,9 @@ export function readSync(rid: number, p: Uint8Array): number | EOF {
} }
} }
/** Read from a file ID into an array buffer. /** Read from a resource ID into an array buffer.
* *
* Resolves with the `number | EOF` for the operation. * Resolves to the `number | EOF` for the operation.
* *
* const file = await Deno.open("/foo/bar.txt"); * const file = await Deno.open("/foo/bar.txt");
* const buf = new Uint8Array(100); * const buf = new Uint8Array(100);
@ -161,9 +172,9 @@ export async function read(rid: number, p: Uint8Array): Promise<number | EOF> {
} }
} }
/** Write synchronously to the file ID the contents of the array buffer. /** Synchronously write to the resource ID the contents of the array buffer.
* *
* Resolves with the number of bytes written. * Resolves to the number of bytes written.
* *
* const encoder = new TextEncoder(); * const encoder = new TextEncoder();
* const data = encoder.encode("Hello world\n"); * const data = encoder.encode("Hello world\n");
@ -182,15 +193,14 @@ export function writeSync(rid: number, p: Uint8Array): number {
} }
} }
/** Write to the file ID the contents of the array buffer. /** Write to the resource ID the contents of the array buffer.
* *
* Resolves with the number of bytes written. * Resolves to the number of bytes written.
* *
* const encoder = new TextEncoder(); * const encoder = new TextEncoder();
* const data = encoder.encode("Hello world\n"); * const data = encoder.encode("Hello world\n");
* const file = await Deno.open("/foo/bar.txt", {create: true, write: true}); * const file = await Deno.open("/foo/bar.txt", {create: true, write: true});
* await Deno.write(file.rid, data); * await Deno.write(file.rid, data);
*
*/ */
export async function write(rid: number, p: Uint8Array): Promise<number> { export async function write(rid: number, p: Uint8Array): Promise<number> {
if (OP_WRITE < 0) { if (OP_WRITE < 0) {
@ -204,7 +214,7 @@ export async function write(rid: number, p: Uint8Array): Promise<number> {
} }
} }
/** Seek a file ID synchronously to the given offset under mode given by `whence`. /** Synchronously seek a file ID to the given offset under mode given by `whence`.
* *
* const file = Deno.openSync("/foo/bar.txt"); * const file = Deno.openSync("/foo/bar.txt");
* Deno.seekSync(file.rid, 0, 0); * Deno.seekSync(file.rid, 0, 0);
@ -226,7 +236,7 @@ export async function seek(
await sendAsyncJson("op_seek", { rid, offset, whence }); await sendAsyncJson("op_seek", { rid, offset, whence });
} }
/** Close the file ID. */ /** Close the given resource ID. */
export function close(rid: number): void { export function close(rid: number): void {
sendSyncJson("op_close", { rid }); sendSyncJson("op_close", { rid });
} }
@ -272,68 +282,57 @@ export class File
} }
} }
/** An instance of `File` for stdin. */ /** An instance of `Deno.File` for `stdin`. */
export const stdin = new File(0); export const stdin = new File(0);
/** An instance of `File` for stdout. */ /** An instance of `Deno.File` for `stdout`. */
export const stdout = new File(1); export const stdout = new File(1);
/** An instance of `File` for stderr. */ /** An instance of `Deno.File` for `stderr`. */
export const stderr = new File(2); export const stderr = new File(2);
export interface OpenOptions { export interface OpenOptions {
/** Sets the option for read access. This option, when true, will indicate that the file should be read-able if opened. */ /** Sets the option for read access. This option, when `true`, means that the
* file should be read-able if opened. */
read?: boolean; read?: boolean;
/** Sets the option for write access. /** Sets the option for write access. This option, when `true`, means that
* This option, when true, will indicate that the file should be write-able if opened. * the file should be write-able if opened. If the file already exists,
* If the file already exists, any write calls on it will overwrite its contents, without truncating it. * any write calls on it will overwrite its contents, by default without
*/ * truncating it. */
write?: boolean; write?: boolean;
/** Sets the option for creating a new file. /**Sets the option for the append mode. This option, when `true`, means that
* This option indicates whether a new file will be created if the file does not yet already exist. * writes will append to a file instead of overwriting previous contents.
* In order for the file to be created, write or append access must be used. * Note that setting `{ write: true, append: true }` has the same effect as
*/ * setting only `{ append: true }`. */
create?: boolean;
/** Sets the option for truncating a previous file.
* If a file is successfully opened with this option set it will truncate the file to 0 length if it already exists.
* The file must be opened with write access for truncate to work.
*/
truncate?: boolean;
/**Sets the option for the append mode.
* This option, when true, means that writes will append to a file instead of overwriting previous contents.
* Note that setting { write: true, append: true } has the same effect as setting only { append: true }.
*/
append?: boolean; append?: boolean;
/** Sets the option to always create a new file. /** Sets the option for truncating a previous file. If a file is
* This option indicates whether a new file will be created. No file is allowed to exist at the target location, also no (dangling) symlink. * successfully opened with this option set it will truncate the file to `0`
* If { createNew: true } is set, create and truncate are ignored. * length if it already exists. The file must be opened with write access
*/ * for truncate to work. */
truncate?: boolean;
/** Sets the option to allow creating a new file, if one doesn't already
* exist at the specified path. Requires write or append access to be
* used. */
create?: boolean;
/** Defaults to `false`. If set to `true`, no file, directory, or symlink is
* allowed to exist at the target location. Requires write or append
* access to be used. When createNew is set to `true`, create and truncate
* are ignored. */
createNew?: boolean; createNew?: boolean;
} }
export type OpenMode = /** A set of string literals which specify the open mode of a file.
/** Read-only. Default. Starts at beginning of file. */ *
| "r" * |Value |Description |
/** Read-write. Start at beginning of file. */ * |------|--------------------------------------------------------------------------------------------------|
| "r+" * |`"r"` |Read-only. Default. Starts at beginning of file. |
/** Write-only. Opens and truncates existing file or creates new one for * |`"r+"`|Read-write. Start at beginning of file. |
* writing only. * |`"w"` |Write-only. Opens and truncates existing file or creates new one for writing only. |
*/ * |`"w+"`|Read-write. Opens and truncates existing file or creates new one for writing and reading. |
| "w" * |`"a"` |Write-only. Opens existing file or creates new one. Each write appends content to the end of file.|
/** Read-write. Opens and truncates existing file or creates new one for * |`"a+"`|Read-write. Behaves like `"a"` and allows to read from file. |
* writing and reading. * |`"x"` |Write-only. Exclusive create - creates new file only if one doesn't exist already. |
*/ * |`"x+"`|Read-write. Behaves like `x` and allows reading from file. |
| "w+" */
/** Write-only. Opens existing file or creates new one. Each write appends export type OpenMode = "r" | "r+" | "w" | "w+" | "a" | "a+" | "x" | "x+";
* content to the end of file.
*/
| "a"
/** Read-write. Behaves like "a" and allows to read from file. */
| "a+"
/** Write-only. Exclusive create - creates new file only if one doesn't exist
* already.
*/
| "x"
/** Read-write. Behaves like `x` and allows to read from file. */
| "x+";
/** Check if OpenOptions is set to valid combination of options. /** Check if OpenOptions is set to valid combination of options.
* @returns Tuple representing if openMode is valid and error message if it's not * @returns Tuple representing if openMode is valid and error message if it's not

View file

@ -8,6 +8,7 @@ export type EOF = typeof EOF;
// Seek whence values. // Seek whence values.
// https://golang.org/pkg/io/#pkg-constants // https://golang.org/pkg/io/#pkg-constants
/** **UNSTABLE**: might remove `"SEEK_"` prefix. Might not use all-caps. */
export enum SeekMode { export enum SeekMode {
SEEK_START = 0, SEEK_START = 0,
SEEK_CURRENT = 1, SEEK_CURRENT = 1,
@ -16,50 +17,79 @@ export enum SeekMode {
// Reader is the interface that wraps the basic read() method. // Reader is the interface that wraps the basic read() method.
// https://golang.org/pkg/io/#Reader // https://golang.org/pkg/io/#Reader
/** **UNSTABLE**: might make `Reader` into iterator of some sort. */
export interface Reader { export interface Reader {
/** Reads up to p.byteLength bytes into `p`. It resolves to the number /** Reads up to `p.byteLength` bytes into `p`. It resolves to the number of
* of bytes read (`0` <= `n` <= `p.byteLength`) and rejects if any error encountered. * bytes read (`0` < `n` <= `p.byteLength`) and rejects if any error
* Even if `read()` returns `n` < `p.byteLength`, it may use all of `p` as * encountered. Even if `read()` resolves to `n` < `p.byteLength`, it may
* scratch space during the call. If some data is available but not * use all of `p` as scratch space during the call. If some data is
* `p.byteLength` bytes, `read()` conventionally returns what is available * available but not `p.byteLength` bytes, `read()` conventionally resolves
* instead of waiting for more. * to what is available instead of waiting for more.
* *
* When `p.byteLength` == `0`, `read()` returns `0` and has no other effects. * When `read()` encounters end-of-file condition, it resolves to
* * `Deno.EOF` symbol.
* When `read()` encounters end-of-file condition, it returns EOF symbol.
* *
* When `read()` encounters an error, it rejects with an error. * When `read()` encounters an error, it rejects with an error.
* *
* Callers should always process the `n` > `0` bytes returned before * Callers should always process the `n` > `0` bytes returned before
* considering the EOF. Doing so correctly handles I/O errors that happen * considering the `EOF`. Doing so correctly handles I/O errors that happen
* after reading some bytes and also both of the allowed EOF behaviors. * after reading some bytes and also both of the allowed EOF behaviors.
* *
* Implementations must not retain `p`. * Implementations should not retain a reference to `p`.
*/ */
read(p: Uint8Array): Promise<number | EOF>; read(p: Uint8Array): Promise<number | EOF>;
} }
export interface SyncReader { export interface SyncReader {
/** Reads up to `p.byteLength` bytes into `p`. It resolves to the number
* of bytes read (`0` < `n` <= `p.byteLength`) and rejects if any error
* encountered. Even if `read()` returns `n` < `p.byteLength`, it may use
* all of `p` as scratch space during the call. If some data is available
* but not `p.byteLength` bytes, `read()` conventionally returns what is
* available instead of waiting for more.
*
* When `readSync()` encounters end-of-file condition, it returns `Deno.EOF`
* symbol.
*
* When `readSync()` encounters an error, it throws with an error.
*
* Callers should always process the `n` > `0` bytes returned before
* considering the `EOF`. Doing so correctly handles I/O errors that happen
* after reading some bytes and also both of the allowed EOF behaviors.
*
* Implementations should not retain a reference to `p`.
*/
readSync(p: Uint8Array): number | EOF; readSync(p: Uint8Array): number | EOF;
} }
// Writer is the interface that wraps the basic write() method. // Writer is the interface that wraps the basic write() method.
// https://golang.org/pkg/io/#Writer // https://golang.org/pkg/io/#Writer
export interface Writer { export interface Writer {
/** Writes `p.byteLength` bytes from `p` to the underlying data /** Writes `p.byteLength` bytes from `p` to the underlying data stream. It
* stream. It resolves to the number of bytes written from `p` (`0` <= `n` <= * resolves to the number of bytes written from `p` (`0` <= `n` <=
* `p.byteLength`) and any error encountered that caused the write to stop * `p.byteLength`) or reject with the error encountered that caused the
* early. `write()` must return a non-null error if it returns `n` < * write to stop early. `write()` must reject with a non-null error if
* `p.byteLength`. write() must not modify the slice data, even temporarily. * would resolve to `n` < `p.byteLength`. `write()` must not modify the
* slice data, even temporarily.
* *
* Implementations must not retain `p`. * Implementations should not retain a reference to `p`.
*/ */
write(p: Uint8Array): Promise<number>; write(p: Uint8Array): Promise<number>;
} }
export interface SyncWriter { export interface SyncWriter {
/** Writes `p.byteLength` bytes from `p` to the underlying data
* stream. It returns the number of bytes written from `p` (`0` <= `n`
* <= `p.byteLength`) and any error encountered that caused the write to
* stop early. `writeSync()` must throw a non-null error if it returns `n` <
* `p.byteLength`. `writeSync()` must not modify the slice data, even
* temporarily.
*
* Implementations should not retain a reference to `p`.
*/
writeSync(p: Uint8Array): number; writeSync(p: Uint8Array): number;
} }
// https://golang.org/pkg/io/#Closer // https://golang.org/pkg/io/#Closer
export interface Closer { export interface Closer {
// The behavior of Close after the first call is undefined. Specific // The behavior of Close after the first call is undefined. Specific
@ -70,19 +100,27 @@ export interface Closer {
// https://golang.org/pkg/io/#Seeker // https://golang.org/pkg/io/#Seeker
export interface Seeker { export interface Seeker {
/** Seek sets the offset for the next `read()` or `write()` to offset, /** Seek sets the offset for the next `read()` or `write()` to offset,
* interpreted according to `whence`: `SeekStart` means relative to the start * interpreted according to `whence`: `SEEK_START` means relative to the
* of the file, `SeekCurrent` means relative to the current offset, and * start of the file, `SEEK_CURRENT` means relative to the current offset,
* `SeekEnd` means relative to the end. Seek returns the new offset relative * and `SEEK_END` means relative to the end.
* to the start of the file and an error, if any.
* *
* Seeking to an offset before the start of the file is an error. Seeking to * Seeking to an offset before the start of the file is an error. Seeking to
* any positive offset is legal, but the behavior of subsequent I/O operations * any positive offset is legal, but the behavior of subsequent I/O
* on the underlying object is implementation-dependent. * operations on the underlying object is implementation-dependent.
*/ */
seek(offset: number, whence: SeekMode): Promise<void>; seek(offset: number, whence: SeekMode): Promise<void>;
} }
export interface SyncSeeker { export interface SyncSeeker {
/** Seek sets the offset for the next `readSync()` or `writeSync()` to
* offset, interpreted according to `whence`: `SEEK_START` means relative
* to the start of the file, `SEEK_CURRENT` means relative to the current
* offset, and `SEEK_END` means relative to the end.
*
* Seeking to an offset before the start of the file is an error. Seeking to
* any positive offset is legal, but the behavior of subsequent I/O
* operations on the underlying object is implementation-dependent.
*/
seekSync(offset: number, whence: SeekMode): void; seekSync(offset: number, whence: SeekMode): void;
} }
@ -104,9 +142,9 @@ export interface ReadWriteCloser extends Reader, Writer, Closer {}
// https://golang.org/pkg/io/#ReadWriteSeeker // https://golang.org/pkg/io/#ReadWriteSeeker
export interface ReadWriteSeeker extends Reader, Writer, Seeker {} export interface ReadWriteSeeker extends Reader, Writer, Seeker {}
/** Copies from `src` to `dst` until either `EOF` is reached on `src` /** Copies from `src` to `dst` until either `EOF` is reached on `src` or an
* or an error occurs. It returns the number of bytes copied and the first * error occurs. It resolves to the number of bytes copied or rejects with
* error encountered while copying, if any. * the first error encountered while copying.
* *
* Because `copy()` is defined to read from `src` until `EOF`, it does not * Because `copy()` is defined to read from `src` until `EOF`, it does not
* treat an `EOF` from `read()` as an error to be reported. * treat an `EOF` from `read()` as an error to be reported.
@ -130,7 +168,7 @@ export async function copy(dst: Writer, src: Reader): Promise<number> {
/** Turns `r` into async iterator. /** Turns `r` into async iterator.
* *
* for await (const chunk of toAsyncIterator(reader)) { * for await (const chunk of toAsyncIterator(reader)) {
* console.log(chunk) * console.log(chunk);
* } * }
*/ */
export function toAsyncIterator(r: Reader): AsyncIterableIterator<Uint8Array> { export function toAsyncIterator(r: Reader): AsyncIterableIterator<Uint8Array> {

File diff suppressed because it is too large Load diff

View file

@ -1185,14 +1185,14 @@ declare namespace __io {
} }
export interface Seeker { export interface Seeker {
/** Seek sets the offset for the next `read()` or `write()` to offset, /** Seek sets the offset for the next `read()` or `write()` to offset,
* interpreted according to `whence`: `SeekStart` means relative to the start * interpreted according to `whence`: `SEEK_START` means relative to the
* of the file, `SeekCurrent` means relative to the current offset, and * start of the file, `SEEK_CURRENT` means relative to the current offset,
* `SeekEnd` means relative to the end. Seek returns the new offset relative * and `SEEK_END` means relative to the end. Seek returns the new offset
* to the start of the file and an error, if any. * relative to the start of the file and an error, if any.
* *
* Seeking to an offset before the start of the file is an error. Seeking to * Seeking to an offset before the start of the file is an error. Seeking to
* any positive offset is legal, but the behavior of subsequent I/O operations * any positive offset is legal, but the behavior of subsequent I/O
* on the underlying object is implementation-dependent. * operations on the underlying object is implementation-dependent.
*/ */
seek(offset: number, whence: SeekMode): Promise<void>; seek(offset: number, whence: SeekMode): Promise<void>;
} }

View file

@ -1,10 +1,11 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync, sendAsync } from "./dispatch_json.ts"; import { sendSync, sendAsync } from "./dispatch_json.ts";
/** Synchronously creates `newname` as a hard link to `oldname`. /** Creates `newname` as a hard link to `oldname`.
* *
* Deno.linkSync("old/name", "new/name"); * Deno.linkSync("old/name", "new/name");
*/ *
* Requires `allow-read` and `allow-write` permissions. */
export function linkSync(oldname: string, newname: string): void { export function linkSync(oldname: string, newname: string): void {
sendSync("op_link", { oldname, newname }); sendSync("op_link", { oldname, newname });
} }
@ -12,7 +13,8 @@ export function linkSync(oldname: string, newname: string): void {
/** Creates `newname` as a hard link to `oldname`. /** Creates `newname` as a hard link to `oldname`.
* *
* await Deno.link("old/name", "new/name"); * await Deno.link("old/name", "new/name");
*/ *
* Requires `allow-read` and `allow-write` permissions. */
export async function link(oldname: string, newname: string): Promise<void> { export async function link(oldname: string, newname: string): Promise<void> {
await sendAsync("op_link", { oldname, newname }); await sendAsync("op_link", { oldname, newname });
} }

View file

@ -2,57 +2,87 @@
import { sendSync, sendAsync } from "./dispatch_json.ts"; import { sendSync, sendAsync } from "./dispatch_json.ts";
export interface MakeTempOptions { export interface MakeTempOptions {
/** Directory where the temporary directory should be created (defaults to
* the env variable TMPDIR, or the system's default, usually /tmp). */
dir?: string; dir?: string;
/** String that should precede the random portion of the temporary
* directory's name. */
prefix?: string; prefix?: string;
/** String that should follow the random portion of the temporary
* directory's name. */
suffix?: string; suffix?: string;
} }
/** makeTempDirSync is the synchronous version of `makeTempDir`. /** Synchronously creates a new temporary directory in the directory `dir`,
* its name beginning with `prefix` and ending with `suffix`.
*
* It returns the full path to the newly created directory.
*
* If `dir` is unspecified, uses the default directory for temporary files.
* Multiple programs calling this function simultaneously will create different
* directories. It is the caller's responsibility to remove the directory when
* no longer needed.
* *
* const tempDirName0 = Deno.makeTempDirSync(); * const tempDirName0 = Deno.makeTempDirSync();
* const tempDirName1 = Deno.makeTempDirSync({ prefix: 'my_temp' }); * const tempDirName1 = Deno.makeTempDirSync({ prefix: 'my_temp' });
*/ *
* Requires `allow-write` permission. */
export function makeTempDirSync(options: MakeTempOptions = {}): string { export function makeTempDirSync(options: MakeTempOptions = {}): string {
return sendSync("op_make_temp_dir", options); return sendSync("op_make_temp_dir", options);
} }
/** makeTempDir creates a new temporary directory in the directory `dir`, its /** Creates a new temporary directory in the directory `dir`, its name
* name beginning with `prefix` and ending with `suffix`. * beginning with `prefix` and ending with `suffix`.
* It returns the full path to the newly created directory. *
* If `dir` is unspecified, tempDir uses the default directory for temporary * It resolves to the full path to the newly created directory.
* files. Multiple programs calling tempDir simultaneously will not choose the *
* same directory. It is the caller's responsibility to remove the directory * If `dir` is unspecified, uses the default directory for temporary files.
* when no longer needed. * Multiple programs calling this function simultaneously will create different
* directories. It is the caller's responsibility to remove the directory when
* no longer needed.
* *
* const tempDirName0 = await Deno.makeTempDir(); * const tempDirName0 = await Deno.makeTempDir();
* const tempDirName1 = await Deno.makeTempDir({ prefix: 'my_temp' }); * const tempDirName1 = await Deno.makeTempDir({ prefix: 'my_temp' });
*/ *
* Requires `allow-write` permission. */
export async function makeTempDir( export async function makeTempDir(
options: MakeTempOptions = {} options: MakeTempOptions = {}
): Promise<string> { ): Promise<string> {
return await sendAsync("op_make_temp_dir", options); return await sendAsync("op_make_temp_dir", options);
} }
/** makeTempFileSync is the synchronous version of `makeTempFile`. /** Synchronously creates a new temporary file in the directory `dir`, its name
* beginning with `prefix` and ending with `suffix`.
*
* It returns the full path to the newly created file.
*
* If `dir` is unspecified, uses the default directory for temporary files.
* Multiple programs calling this function simultaneously will create different
* files. It is the caller's responsibility to remove the file when
* no longer needed.
* *
* const tempFileName0 = Deno.makeTempFileSync(); * const tempFileName0 = Deno.makeTempFileSync();
* const tempFileName1 = Deno.makeTempFileSync({ prefix: 'my_temp' }); * const tempFileName1 = Deno.makeTempFileSync({ prefix: 'my_temp' });
*/ *
* Requires `allow-write` permission. */
export function makeTempFileSync(options: MakeTempOptions = {}): string { export function makeTempFileSync(options: MakeTempOptions = {}): string {
return sendSync("op_make_temp_file", options); return sendSync("op_make_temp_file", options);
} }
/** makeTempFile creates a new temporary file in the directory `dir`, its /** Creates a new temporary file in the directory `dir`, its name
* name beginning with `prefix` and ending with `suffix`. * beginning with `prefix` and ending with `suffix`.
* It returns the full path to the newly created file. *
* If `dir` is unspecified, tempFile uses the default directory for temporary * It resolves to the full path to the newly created file.
* files. Multiple programs calling tempFile simultaneously will not choose the *
* same directory. It is the caller's responsibility to remove the file * If `dir` is unspecified, uses the default directory for temporary files.
* when no longer needed. * Multiple programs calling this function simultaneously will create different
* files. It is the caller's responsibility to remove the file when
* no longer needed.
* *
* const tempFileName0 = await Deno.makeTempFile(); * const tempFileName0 = await Deno.makeTempFile();
* const tempFileName1 = await Deno.makeTempFile({ prefix: 'my_temp' }); * const tempFileName1 = await Deno.makeTempFile({ prefix: 'my_temp' });
*/ *
* Requires `allow-write` permission. */
export async function makeTempFile( export async function makeTempFile(
options: MakeTempOptions = {} options: MakeTempOptions = {}
): Promise<string> { ): Promise<string> {

View file

@ -26,19 +26,24 @@ function mkdirArgs(
} }
export interface MkdirOption { export interface MkdirOption {
/** Defaults to `false`. If set to `true`, means that any intermediate
* directories will also be created (as with the shell command `mkdir -p`).
* Intermediate directories are created with the same permissions.
* When recursive is set to `true`, succeeds silently (without changing any
* permissions) if a directory already exists at the path. */
recursive?: boolean; recursive?: boolean;
/** Permissions to use when creating the directory (defaults to `0o777`,
* before the process's umask).
* Does nothing/raises on Windows. */
mode?: number; mode?: number;
} }
/** Creates a new directory with the specified path synchronously. /** Synchronously creates a new directory with the specified path.
* If `recursive` is set to true, nested directories will be created (also known
* as "mkdir -p").
* `mode` sets permission bits (before umask) on UNIX and does nothing on
* Windows.
* *
* Deno.mkdirSync("new_dir"); * Deno.mkdirSync("new_dir");
* Deno.mkdirSync("nested/directories", { recursive: true }); * Deno.mkdirSync("nested/directories", { recursive: true });
*/ *
* Requires `allow-write` permission. */
export function mkdirSync( export function mkdirSync(
path: string, path: string,
optionsOrRecursive?: MkdirOption | boolean, optionsOrRecursive?: MkdirOption | boolean,
@ -48,14 +53,11 @@ export function mkdirSync(
} }
/** Creates a new directory with the specified path. /** Creates a new directory with the specified path.
* If `recursive` is set to true, nested directories will be created (also known
* as "mkdir -p").
* `mode` sets permission bits (before umask) on UNIX and does nothing on
* Windows.
* *
* await Deno.mkdir("new_dir"); * await Deno.mkdir("new_dir");
* await Deno.mkdir("nested/directories", { recursive: true }); * await Deno.mkdir("nested/directories", { recursive: true });
*/ *
* Requires `allow-write` permission. */
export async function mkdir( export async function mkdir(
path: string, path: string,
optionsOrRecursive?: MkdirOption | boolean, optionsOrRecursive?: MkdirOption | boolean,

View file

@ -15,19 +15,23 @@ function res(response: ReadDirResponse): FileInfo[] {
); );
} }
/** Reads the directory given by path and returns a list of file info /** Synchronously reads the directory given by `path` and returns an array of
* synchronously. * `Deno.FileInfo`.
* *
* const files = Deno.readDirSync("/"); * const files = Deno.readDirSync("/");
*/ *
* Requires `allow-read` permission. */
export function readDirSync(path: string): FileInfo[] { export function readDirSync(path: string): FileInfo[] {
return res(sendSync("op_read_dir", { path })); return res(sendSync("op_read_dir", { path }));
} }
/** Reads the directory given by path and returns a list of file info. /** UNSTABLE: Maybe need to return an `AsyncIterable`.
*
* Reads the directory given by `path` and resolves to an array of `Deno.FileInfo`.
* *
* const files = await Deno.readDir("/"); * const files = await Deno.readDir("/");
*/ *
* Requires `allow-read` permission. */
export async function readDir(path: string): Promise<FileInfo[]> { export async function readDir(path: string): Promise<FileInfo[]> {
return res(await sendAsync("op_read_dir", { path })); return res(await sendAsync("op_read_dir", { path }));
} }

View file

@ -2,12 +2,13 @@
import { open, openSync } from "./files.ts"; import { open, openSync } from "./files.ts";
import { readAll, readAllSync } from "./buffer.ts"; import { readAll, readAllSync } from "./buffer.ts";
/** Read the entire contents of a file synchronously. /** Reads and returns the entire contents of a file.
* *
* const decoder = new TextDecoder("utf-8"); * const decoder = new TextDecoder("utf-8");
* const data = Deno.readFileSync("hello.txt"); * const data = Deno.readFileSync("hello.txt");
* console.log(decoder.decode(data)); * console.log(decoder.decode(data));
*/ *
* Requires `allow-read` permission. */
export function readFileSync(filename: string): Uint8Array { export function readFileSync(filename: string): Uint8Array {
const file = openSync(filename); const file = openSync(filename);
const contents = readAllSync(file); const contents = readAllSync(file);
@ -15,12 +16,13 @@ export function readFileSync(filename: string): Uint8Array {
return contents; return contents;
} }
/** Read the entire contents of a file. /** Reads and resolves to the entire contents of a file.
* *
* const decoder = new TextDecoder("utf-8"); * const decoder = new TextDecoder("utf-8");
* const data = await Deno.readFile("hello.txt"); * const data = await Deno.readFile("hello.txt");
* console.log(decoder.decode(data)); * console.log(decoder.decode(data));
*/ *
* Requires `allow-read` permission. */
export async function readFile(filename: string): Promise<Uint8Array> { export async function readFile(filename: string): Promise<Uint8Array> {
const file = await open(filename); const file = await open(filename);
const contents = await readAll(file); const contents = await readAll(file);

View file

@ -1,18 +1,20 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync, sendAsync } from "./dispatch_json.ts"; import { sendSync, sendAsync } from "./dispatch_json.ts";
/** Returns the destination of the named symbolic link synchronously. /** Returns the destination of the named symbolic link.
* *
* const targetPath = Deno.readlinkSync("symlink/path"); * const targetPath = Deno.readlinkSync("symlink/path");
*/ *
* Requires `allow-read` permission. */
export function readlinkSync(name: string): string { export function readlinkSync(name: string): string {
return sendSync("op_read_link", { name }); return sendSync("op_read_link", { name });
} }
/** Returns the destination of the named symbolic link. /** Resolves to the destination of the named symbolic link.
* *
* const targetPath = await Deno.readlink("symlink/path"); * const targetPath = await Deno.readlink("symlink/path");
*/ *
* Requires `allow-read` permission. */
export async function readlink(name: string): Promise<string> { export async function readlink(name: string): Promise<string> {
return await sendAsync("op_read_link", { name }); return await sendAsync("op_read_link", { name });
} }

View file

@ -2,27 +2,29 @@
import { sendSync, sendAsync } from "./dispatch_json.ts"; import { sendSync, sendAsync } from "./dispatch_json.ts";
export interface RemoveOption { export interface RemoveOption {
/** Defaults to `false`. If set to `true`, path will be removed even if
* it's a non-empty directory. */
recursive?: boolean; recursive?: boolean;
} }
/** Removes the named file, directory or symlink synchronously. Would throw /** Synchronously removes the named file or directory. Throws error if
* error if permission denied, not found, or directory not empty if `recursive` * permission denied, path not found, or path is a non-empty directory and
* set to false. * the `recursive` option isn't set to `true`.
* `recursive` is set to false by default.
* *
* Deno.removeSync("/path/to/dir/or/file", {recursive: false}); * Deno.removeSync("/path/to/dir/or/file", { recursive: false });
*/ *
* Requires `allow-write` permission. */
export function removeSync(path: string, options: RemoveOption = {}): void { export function removeSync(path: string, options: RemoveOption = {}): void {
sendSync("op_remove", { path, recursive: !!options.recursive }); sendSync("op_remove", { path, recursive: !!options.recursive });
} }
/** Removes the named file, directory or symlink. Would throw error if /** Removes the named file or directory. Throws error if permission denied,
* permission denied, not found, or directory not empty if `recursive` set * path not found, or path is a non-empty directory and the `recursive`
* to false. * option isn't set to `true`.
* `recursive` is set to false by default.
* *
* await Deno.remove("/path/to/dir/or/file", {recursive: false}); * await Deno.remove("/path/to/dir/or/file", { recursive: false });
*/ *
* Requires `allow-write` permission. */
export async function remove( export async function remove(
path: string, path: string,
options: RemoveOption = {} options: RemoveOption = {}

View file

@ -7,7 +7,8 @@ import { sendSync, sendAsync } from "./dispatch_json.ts";
* directories. * directories.
* *
* Deno.renameSync("old/path", "new/path"); * Deno.renameSync("old/path", "new/path");
*/ *
* Requires `allow-read` and `allow-write` permissions. */
export function renameSync(oldpath: string, newpath: string): void { export function renameSync(oldpath: string, newpath: string): void {
sendSync("op_rename", { oldpath, newpath }); sendSync("op_rename", { oldpath, newpath });
} }
@ -17,7 +18,8 @@ export function renameSync(oldpath: string, newpath: string): void {
* when `oldpath` and `newpath` are in different directories. * when `oldpath` and `newpath` are in different directories.
* *
* await Deno.rename("old/path", "new/path"); * await Deno.rename("old/path", "new/path");
*/ *
* Requires `allow-read` and `allow-write`. */
export async function rename(oldpath: string, newpath: string): Promise<void> { export async function rename(oldpath: string, newpath: string): Promise<void> {
await sendAsync("op_rename", { oldpath, newpath }); await sendAsync("op_rename", { oldpath, newpath });
} }

View file

@ -23,12 +23,13 @@ export interface StatResponse {
blocks: number; blocks: number;
} }
/** Queries the file system for information on the path provided. If the given /** Resolves to a `Deno.FileInfo` for the specified path. If path is a
* path is a symlink information about the symlink will be returned. * symlink, information for the symlink will be returned.
* *
* const fileInfo = await Deno.lstat("hello.txt"); * const fileInfo = await Deno.lstat("hello.txt");
* assert(fileInfo.isFile()); * assert(fileInfo.isFile());
*/ *
* Requires `allow-read` permission. */
export async function lstat(filename: string): Promise<FileInfo> { export async function lstat(filename: string): Promise<FileInfo> {
const res = (await sendAsync("op_stat", { const res = (await sendAsync("op_stat", {
filename, filename,
@ -37,13 +38,13 @@ export async function lstat(filename: string): Promise<FileInfo> {
return new FileInfoImpl(res); return new FileInfoImpl(res);
} }
/** Queries the file system for information on the path provided synchronously. /** Synchronously returns a `Deno.FileInfo` for the specified path. If
* If the given path is a symlink information about the symlink will be * path is a symlink, information for the symlink will be returned.
* returned.
* *
* const fileInfo = Deno.lstatSync("hello.txt"); * const fileInfo = Deno.lstatSync("hello.txt");
* assert(fileInfo.isFile()); * assert(fileInfo.isFile());
*/ *
* Requires `allow-read` permission. */
export function lstatSync(filename: string): FileInfo { export function lstatSync(filename: string): FileInfo {
const res = sendSync("op_stat", { const res = sendSync("op_stat", {
filename, filename,
@ -52,12 +53,13 @@ export function lstatSync(filename: string): FileInfo {
return new FileInfoImpl(res); return new FileInfoImpl(res);
} }
/** Queries the file system for information on the path provided. `stat` Will /** Resolves to a `Deno.FileInfo` for the specified path. Will always follow
* always follow symlinks. * symlinks.
* *
* const fileInfo = await Deno.stat("hello.txt"); * const fileInfo = await Deno.stat("hello.txt");
* assert(fileInfo.isFile()); * assert(fileInfo.isFile());
*/ *
* Requires `allow-read` permission. */
export async function stat(filename: string): Promise<FileInfo> { export async function stat(filename: string): Promise<FileInfo> {
const res = (await sendAsync("op_stat", { const res = (await sendAsync("op_stat", {
filename, filename,
@ -66,12 +68,13 @@ export async function stat(filename: string): Promise<FileInfo> {
return new FileInfoImpl(res); return new FileInfoImpl(res);
} }
/** Queries the file system for information on the path provided synchronously. /** Synchronously returns a `Deno.FileInfo` for the specified path. Will
* `statSync` Will always follow symlinks. * always follow symlinks.
* *
* const fileInfo = Deno.statSync("hello.txt"); * const fileInfo = Deno.statSync("hello.txt");
* assert(fileInfo.isFile()); * assert(fileInfo.isFile());
*/ *
* Requires `allow-read` permission. */
export function statSync(filename: string): FileInfo { export function statSync(filename: string): FileInfo {
const res = sendSync("op_stat", { const res = sendSync("op_stat", {
filename, filename,

View file

@ -52,9 +52,9 @@ testPerm({ read: true }, async function lstatSyncSuccess(): Promise<void> {
assert(!modulesInfo.isDirectory()); assert(!modulesInfo.isDirectory());
assert(modulesInfo.isSymlink()); assert(modulesInfo.isSymlink());
const i = Deno.lstatSync("core"); const coreInfo = Deno.lstatSync("core");
assert(i.isDirectory()); assert(coreInfo.isDirectory());
assert(!i.isSymlink()); assert(!coreInfo.isSymlink());
}); });
testPerm({ read: false }, async function lstatSyncPerm(): Promise<void> { testPerm({ read: false }, async function lstatSyncPerm(): Promise<void> {
@ -92,9 +92,9 @@ testPerm({ read: true }, async function statSuccess(): Promise<void> {
assert(modulesInfo.isDirectory()); assert(modulesInfo.isDirectory());
assert(!modulesInfo.isSymlink()); assert(!modulesInfo.isSymlink());
const i = await Deno.stat("cli/tests"); const testsInfo = await Deno.stat("cli/tests");
assert(i.isDirectory()); assert(testsInfo.isDirectory());
assert(!i.isSymlink()); assert(!testsInfo.isSymlink());
}); });
testPerm({ read: false }, async function statPerm(): Promise<void> { testPerm({ read: false }, async function statPerm(): Promise<void> {
@ -132,9 +132,9 @@ testPerm({ read: true }, async function lstatSuccess(): Promise<void> {
assert(!modulesInfo.isDirectory()); assert(!modulesInfo.isDirectory());
assert(modulesInfo.isSymlink()); assert(modulesInfo.isSymlink());
const i = await Deno.lstat("core"); const coreInfo = await Deno.lstat("core");
assert(i.isDirectory()); assert(coreInfo.isDirectory());
assert(!i.isSymlink()); assert(!coreInfo.isSymlink());
}); });
testPerm({ read: false }, async function lstatPerm(): Promise<void> { testPerm({ read: false }, async function lstatPerm(): Promise<void> {

View file

@ -3,12 +3,15 @@ import { sendSync, sendAsync } from "./dispatch_json.ts";
import * as util from "./util.ts"; import * as util from "./util.ts";
import { build } from "./build.ts"; import { build } from "./build.ts";
/** Synchronously creates `newname` as a symbolic link to `oldname`. The type /** **UNSTABLE**: `type` argument type may be changed to `"dir" | "file"`.
* argument can be set to `dir` or `file` and is only available on Windows *
* (ignored on other platforms). * Creates `newname` as a symbolic link to `oldname`. The type argument can be
* set to `dir` or `file`. Is only available on Windows and ignored on other
* platforms.
* *
* Deno.symlinkSync("old/name", "new/name"); * Deno.symlinkSync("old/name", "new/name");
*/ *
* Requires `allow-read` and `allow-write` permissions. */
export function symlinkSync( export function symlinkSync(
oldname: string, oldname: string,
newname: string, newname: string,
@ -20,12 +23,15 @@ export function symlinkSync(
sendSync("op_symlink", { oldname, newname }); sendSync("op_symlink", { oldname, newname });
} }
/** Creates `newname` as a symbolic link to `oldname`. The type argument can be /** **UNSTABLE**: `type` argument may be changed to "dir" | "file"
* set to `dir` or `file` and is only available on Windows (ignored on other *
* platforms). * Creates `newname` as a symbolic link to `oldname`. The type argument can be
* set to `dir` or `file`. Is only available on Windows and ignored on other
* platforms.
* *
* await Deno.symlink("old/name", "new/name"); * await Deno.symlink("old/name", "new/name");
*/ *
* Requires `allow-read` and `allow-write` permissions. */
export async function symlink( export async function symlink(
oldname: string, oldname: string,
newname: string, newname: string,

View file

@ -13,21 +13,21 @@ function coerceLen(len?: number): number {
return len; return len;
} }
/** Truncates or extends the specified file synchronously, updating the size of /** Synchronously truncates or extends the specified file, to reach the
* this file to become size. * specified `len`.
* *
* Deno.truncateSync("hello.txt", 10); * Deno.truncateSync("hello.txt", 10);
*/ *
* Requires `allow-write` permission. */
export function truncateSync(name: string, len?: number): void { export function truncateSync(name: string, len?: number): void {
sendSync("op_truncate", { name, len: coerceLen(len) }); sendSync("op_truncate", { name, len: coerceLen(len) });
} }
/** /** Truncates or extends the specified file, to reach the specified `len`.
* Truncates or extends the specified file, updating the size of this file to
* become size.
* *
* await Deno.truncate("hello.txt", 10); * await Deno.truncate("hello.txt", 10);
*/ *
* Requires `allow-write` permission. */
export async function truncate(name: string, len?: number): Promise<void> { export async function truncate(name: string, len?: number): Promise<void> {
await sendAsync("op_truncate", { name, len: coerceLen(len) }); await sendAsync("op_truncate", { name, len: coerceLen(len) });
} }

View file

@ -5,12 +5,15 @@ function toSecondsFromEpoch(v: number | Date): number {
return v instanceof Date ? v.valueOf() / 1000 : v; return v instanceof Date ? v.valueOf() / 1000 : v;
} }
/** Synchronously changes the access and modification times of a file system /** **UNSTABLE**: needs investigation into high precision time.
*
* Synchronously changes the access and modification times of a file system
* object referenced by `filename`. Given times are either in seconds * object referenced by `filename`. Given times are either in seconds
* (Unix epoch time) or as `Date` objects. * (Unix epoch time) or as `Date` objects.
* *
* Deno.utimeSync("myfile.txt", 1556495550, new Date()); * Deno.utimeSync("myfile.txt", 1556495550, new Date());
*/ *
* Requires `allow-write` permission. */
export function utimeSync( export function utimeSync(
filename: string, filename: string,
atime: number | Date, atime: number | Date,
@ -24,12 +27,15 @@ export function utimeSync(
}); });
} }
/** Changes the access and modification times of a file system object /** **UNSTABLE**: needs investigation into high precision time.
*
* Changes the access and modification times of a file system object
* referenced by `filename`. Given times are either in seconds * referenced by `filename`. Given times are either in seconds
* (Unix epoch time) or as `Date` objects. * (Unix epoch time) or as `Date` objects.
* *
* await Deno.utime("myfile.txt", 1556495550, new Date()); * await Deno.utime("myfile.txt", 1556495550, new Date());
*/ *
* Requires `allow-write` permission. */
export async function utime( export async function utime(
filename: string, filename: string,
atime: number | Date, atime: number | Date,

View file

@ -4,22 +4,26 @@ import { open, openSync } from "./files.ts";
import { chmod, chmodSync } from "./chmod.ts"; import { chmod, chmodSync } from "./chmod.ts";
import { writeAll, writeAllSync } from "./buffer.ts"; import { writeAll, writeAllSync } from "./buffer.ts";
/** Options for writing to a file. /** Options for writing to a file. */
* `perm` would change the file's permission if set.
* `create` decides if the file should be created if not exists (default: true)
* `append` decides if the file should be appended (default: false)
*/
export interface WriteFileOptions { export interface WriteFileOptions {
perm?: number; /** Defaults to `false`. If set to `true`, will append to a file instead of
create?: boolean; * overwriting previous contents. */
append?: boolean; append?: boolean;
/** Sets the option to allow creating a new file, if one doesn't already
* exist at the specified path (defaults to `true`). */
create?: boolean;
/** Permissions always applied to file. */
perm?: number;
} }
/** Write a new file, with given filename and data synchronously. /** Synchronously write data to the given path, by default creating a new
* file if needed, else overwriting.
* *
* const encoder = new TextEncoder(); * const encoder = new TextEncoder();
* const data = encoder.encode("Hello world\n"); * const data = encoder.encode("Hello world\n");
* Deno.writeFileSync("hello.txt", data); * Deno.writeFileSync("hello.txt", data);
*
* Requires `allow-write` permission, and `allow-read` if create is `false`.
*/ */
export function writeFileSync( export function writeFileSync(
filename: string, filename: string,
@ -45,11 +49,14 @@ export function writeFileSync(
file.close(); file.close();
} }
/** Write a new file, with given filename and data. /** Write data to the given path, by default creating a new file if needed,
* else overwriting.
* *
* const encoder = new TextEncoder(); * const encoder = new TextEncoder();
* const data = encoder.encode("Hello world\n"); * const data = encoder.encode("Hello world\n");
* await Deno.writeFile("hello.txt", data); * await Deno.writeFile("hello.txt", data);
*
* Requires `allow-write` permission, and `allow-read` if create is `false`.
*/ */
export async function writeFile( export async function writeFile(
filename: string, filename: string,

View file

@ -13,9 +13,7 @@ use std::path::Path;
use std::time::UNIX_EPOCH; use std::time::UNIX_EPOCH;
#[cfg(unix)] #[cfg(unix)]
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::{MetadataExt, PermissionsExt};
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
pub fn init(i: &mut Isolate, s: &State) { pub fn init(i: &mut Isolate, s: &State) {
i.register_op("op_chdir", s.stateful_json_op(op_chdir)); i.register_op("op_chdir", s.stateful_json_op(op_chdir));
@ -104,7 +102,7 @@ fn op_chmod(
debug!("op_chmod {}", path.display()); debug!("op_chmod {}", path.display());
// Still check file/dir exists on windows // Still check file/dir exists on windows
let _metadata = fs::metadata(&path)?; let _metadata = fs::metadata(&path)?;
#[cfg(any(unix))] #[cfg(unix)]
{ {
let mut permissions = _metadata.permissions(); let mut permissions = _metadata.permissions();
permissions.set_mode(args.mode); permissions.set_mode(args.mode);
@ -136,10 +134,8 @@ fn op_chown(
let is_sync = args.promise_id.is_none(); let is_sync = args.promise_id.is_none();
blocking_json(is_sync, move || { blocking_json(is_sync, move || {
debug!("op_chown {}", path.display()); debug!("op_chown {}", path.display());
match deno_fs::chown(args.path.as_ref(), args.uid, args.gid) { deno_fs::chown(args.path.as_ref(), args.uid, args.gid)?;
Ok(_) => Ok(json!({})), Ok(json!({}))
Err(e) => Err(OpError::from(e)),
}
}) })
} }
@ -201,13 +197,14 @@ fn op_copy_file(
debug!("op_copy_file {} {}", from.display(), to.display()); debug!("op_copy_file {} {}", from.display(), to.display());
let is_sync = args.promise_id.is_none(); let is_sync = args.promise_id.is_none();
blocking_json(is_sync, move || { blocking_json(is_sync, move || {
// On *nix, Rust deem non-existent path as invalid input // On *nix, Rust reports non-existent `from` as ErrorKind::InvalidInput
// See https://github.com/rust-lang/rust/issues/54800 // See https://github.com/rust-lang/rust/issues/54800
// Once the issue is reolved, we should remove this workaround. // Once the issue is resolved, we should remove this workaround.
if cfg!(unix) && !from.is_file() { if cfg!(unix) && !from.is_file() {
return Err(OpError::not_found("File not found".to_string())); return Err(OpError::not_found("File not found".to_string()));
} }
// returns length of from as u64 (we ignore)
fs::copy(&from, &to)?; fs::copy(&from, &to)?;
Ok(json!({})) Ok(json!({}))
}) })
@ -451,13 +448,13 @@ fn op_symlink(
state.check_write(&newname)?; state.check_write(&newname)?;
// TODO Use type for Windows. // TODO Use type for Windows.
if cfg!(windows) { if cfg!(not(unix)) {
return Err(OpError::other("Not implemented".to_string())); return Err(OpError::other("Not implemented".to_string()));
} }
let is_sync = args.promise_id.is_none(); let is_sync = args.promise_id.is_none();
blocking_json(is_sync, move || { blocking_json(is_sync, move || {
debug!("op_symlink {} {}", oldname.display(), newname.display()); debug!("op_symlink {} {}", oldname.display(), newname.display());
#[cfg(any(unix))] #[cfg(unix)]
std::os::unix::fs::symlink(&oldname, &newname)?; std::os::unix::fs::symlink(&oldname, &newname)?;
Ok(json!({})) Ok(json!({}))
}) })
@ -597,7 +594,7 @@ fn op_make_temp_file(
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct Utime { struct UtimeArgs {
promise_id: Option<u64>, promise_id: Option<u64>,
filename: String, filename: String,
atime: u64, atime: u64,
@ -609,11 +606,11 @@ fn op_utime(
args: Value, args: Value,
_zero_copy: Option<ZeroCopyBuf>, _zero_copy: Option<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> { ) -> Result<JsonOp, OpError> {
let args: Utime = serde_json::from_value(args)?; let args: UtimeArgs = serde_json::from_value(args)?;
state.check_write(Path::new(&args.filename))?; state.check_write(Path::new(&args.filename))?;
let is_sync = args.promise_id.is_none(); let is_sync = args.promise_id.is_none();
blocking_json(is_sync, move || { blocking_json(is_sync, move || {
debug!("op_utimes {} {} {}", args.filename, args.atime, args.mtime); debug!("op_utime {} {} {}", args.filename, args.atime, args.mtime);
utime::set_file_times(args.filename, args.atime, args.mtime)?; utime::set_file_times(args.filename, args.atime, args.mtime)?;
Ok(json!({})) Ok(json!({}))
}) })