diff --git a/std/node/_fs/_fs_chown.ts b/std/node/_fs/_fs_chown.ts new file mode 100644 index 0000000000..008b30c47e --- /dev/null +++ b/std/node/_fs/_fs_chown.ts @@ -0,0 +1,37 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +import { CallbackWithError } from "./_fs_common.ts"; + +/** + * TODO: Also accept 'path' parameter as a Node polyfill Buffer or URL type once these + * are implemented. See https://github.com/denoland/deno/issues/3403 + */ +export function chown( + path: string, + uid: number, + gid: number, + callback: CallbackWithError +): void { + new Promise(async (resolve, reject) => { + try { + await Deno.chown(path, uid, gid); + resolve(); + } catch (err) { + reject(err); + } + }) + .then(() => { + callback(); + }) + .catch(err => { + callback(err); + }); +} + +/** + * TODO: Also accept 'path' parameter as a Node polyfill Buffer or URL type once these + * are implemented. See https://github.com/denoland/deno/issues/3403 + */ +export function chownSync(path: string, uid: number, gid: number): void { + Deno.chownSync(path, uid, gid); +} diff --git a/std/node/_fs/_fs_chown_test.ts b/std/node/_fs/_fs_chown_test.ts new file mode 100644 index 0000000000..51a463d887 --- /dev/null +++ b/std/node/_fs/_fs_chown_test.ts @@ -0,0 +1,50 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +const { test } = Deno; +import { fail, assertEquals } from "../../testing/asserts.ts"; +import { chown, chownSync } from "./_fs_chown.ts"; + +if (Deno.build.os !== "win") { + //chown is difficult to test. Best we can do is set the existing user id/group id again + test({ + name: "ASYNC: setting existing uid/gid works as expected (non-Windows)", + async fn() { + const tempFile: string = await Deno.makeTempFile(); + const originalUserId: number | null = (await Deno.lstat(tempFile)).uid; + const originalGroupId: number | null = (await Deno.lstat(tempFile)).gid; + await new Promise((resolve, reject) => { + chown(tempFile, originalUserId!, originalGroupId!, err => { + if (err) reject(err); + else resolve(); + }); + }) + .then(() => { + const newUserId: number | null = Deno.lstatSync(tempFile).uid; + const newGroupId: number | null = Deno.lstatSync(tempFile).gid; + assertEquals(newUserId, originalUserId); + assertEquals(newGroupId, originalGroupId); + }) + .catch(() => { + fail(); + }) + .finally(() => { + Deno.removeSync(tempFile); + }); + } + }); + + test({ + name: "SYNC: setting existing uid/gid works as expected (non-Windows)", + fn() { + const tempFile: string = Deno.makeTempFileSync(); + const originalUserId: number | null = Deno.lstatSync(tempFile).uid; + const originalGroupId: number | null = Deno.lstatSync(tempFile).gid; + chownSync(tempFile, originalUserId!, originalGroupId!); + + const newUserId: number | null = Deno.lstatSync(tempFile).uid; + const newGroupId: number | null = Deno.lstatSync(tempFile).gid; + assertEquals(newUserId, originalUserId); + assertEquals(newGroupId, originalGroupId); + Deno.removeSync(tempFile); + } + }); +} diff --git a/std/node/_fs/_fs_close.ts b/std/node/_fs/_fs_close.ts new file mode 100644 index 0000000000..e19eb932ec --- /dev/null +++ b/std/node/_fs/_fs_close.ts @@ -0,0 +1,24 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +import { CallbackWithError } from "./_fs_common.ts"; + +export function close(fd: number, callback: CallbackWithError): void { + new Promise(async (resolve, reject) => { + try { + Deno.close(fd); + resolve(); + } catch (err) { + reject(err); + } + }) + .then(() => { + callback(); + }) + .catch(err => { + callback(err); + }); +} + +export function closeSync(fd: number): void { + Deno.close(fd); +} diff --git a/std/node/_fs/_fs_close_test.ts b/std/node/_fs/_fs_close_test.ts new file mode 100644 index 0000000000..2c71172488 --- /dev/null +++ b/std/node/_fs/_fs_close_test.ts @@ -0,0 +1,42 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +const { test } = Deno; +import { fail, assert } from "../../testing/asserts.ts"; +import { close, closeSync } from "./_fs_close.ts"; + +test({ + name: "ASYNC: File is closed", + async fn() { + const tempFile: string = await Deno.makeTempFile(); + const file: Deno.File = await Deno.open(tempFile); + + assert(Deno.resources()[file.rid]); + await new Promise((resolve, reject) => { + close(file.rid, err => { + if (err) reject(); + else resolve(); + }); + }) + .then(async () => { + assert(!Deno.resources()[file.rid]); + }) + .catch(() => { + fail("No error expected"); + }) + .finally(async () => { + await Deno.remove(tempFile); + }); + } +}); + +test({ + name: "SYNC: File is closed", + fn() { + const tempFile: string = Deno.makeTempFileSync(); + const file: Deno.File = Deno.openSync(tempFile); + + assert(Deno.resources()[file.rid]); + closeSync(file.rid); + assert(!Deno.resources()[file.rid]); + Deno.removeSync(tempFile); + } +}); diff --git a/std/node/querystring.ts b/std/node/querystring.ts index a5b2e7f056..fc5a00a13e 100644 --- a/std/node/querystring.ts +++ b/std/node/querystring.ts @@ -1,3 +1,5 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + interface ParseOptions { decodeURIComponent?: (string: string) => string; maxKeys?: number;