0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

Implement deno.readlink() (#797)

This commit is contained in:
Mani Maghsoudlou 2018-09-24 21:20:49 -07:00 committed by Ryan Dahl
parent d957f8ebc2
commit ad5065e23e
7 changed files with 133 additions and 1 deletions

View file

@ -83,6 +83,7 @@ ts_sources = [
"js/read_file.ts",
"js/remove.ts",
"js/rename.ts",
"js/read_link.ts",
"js/stat.ts",
"js/symlink.ts",
"js/text_encoding.ts",

View file

@ -5,8 +5,9 @@ export { env, exit } from "./os";
export { mkdirSync, mkdir } from "./mkdir";
export { makeTempDirSync, makeTempDir } from "./make_temp_dir";
export { removeSync, remove, removeAllSync, removeAll } from "./remove";
export { readFileSync, readFile } from "./read_file";
export { renameSync, rename } from "./rename";
export { readFileSync, readFile } from "./read_file";
export { readlinkSync, readlink } from "./read_link";
export { FileInfo, statSync, lstatSync, stat, lstat } from "./stat";
export { symlinkSync, symlink } from "./symlink";
export { writeFileSync, writeFile } from "./write_file";

46
js/read_link.ts Normal file
View file

@ -0,0 +1,46 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
import * as fbs from "gen/msg_generated";
import { flatbuffers } from "flatbuffers";
import { assert } from "./util";
import * as dispatch from "./dispatch";
/**
* Returns the destination of the named symbolic link synchronously.
*
* import { readlinkSync } from "deno";
* const targetPath = readlinkSync("symlink/path");
*/
export function readlinkSync(name: string): string {
return res(dispatch.sendSync(...req(name)));
}
/**
* Returns the destination of the named symbolic link.
*
* import { readlink } from "deno";
* const targetPath = await readlink("symlink/path");
*/
export async function readlink(name: string): Promise<string> {
return res(await dispatch.sendAsync(...req(name)));
}
function req(
name: string
): [flatbuffers.Builder, fbs.Any, flatbuffers.Offset] {
const builder = new flatbuffers.Builder();
const name_ = builder.createString(name);
fbs.Readlink.startReadlink(builder);
fbs.Readlink.addName(builder, name_);
const msg = fbs.Readlink.endReadlink(builder);
return [builder, fbs.Any.Readlink, msg];
}
function res(baseRes: null | fbs.Base): string {
assert(baseRes !== null);
assert(fbs.Any.ReadlinkRes === baseRes!.msgType());
const res = new fbs.ReadlinkRes();
assert(baseRes!.msg(res) !== null);
const path = res.path();
assert(path !== null);
return path!;
}

44
js/read_link_test.ts Normal file
View file

@ -0,0 +1,44 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
import { test, testPerm, assert, assertEqual } from "./test_util.ts";
import * as deno from "deno";
testPerm({ write: true }, function readlinkSyncSuccess() {
const testDir = deno.makeTempDirSync() + "/test-readlink-sync";
const target = testDir + "/target";
const symlink = testDir + "/symln";
deno.mkdirSync(target);
// TODO Add test for Windows once symlink is implemented for Windows.
// See https://github.com/denoland/deno/issues/815.
if (deno.platform !== "win32") {
deno.symlinkSync(target, symlink);
const targetPath = deno.readlinkSync(symlink);
assertEqual(targetPath, target);
}
});
test(function readlinkSyncNotFound() {
let caughtError = false;
let data;
try {
data = deno.readlinkSync("bad_filename");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.NotFound);
}
assert(caughtError);
assertEqual(data, undefined);
});
testPerm({ write: true }, async function readlinkSuccess() {
const testDir = deno.makeTempDirSync() + "/test-readlink";
const target = testDir + "/target";
const symlink = testDir + "/symln";
deno.mkdirSync(target);
// TODO Add test for Windows once symlink is implemented for Windows.
// See https://github.com/denoland/deno/issues/815.
if (deno.platform !== "win32") {
deno.symlinkSync(target, symlink);
const targetPath = await deno.readlink(symlink);
assertEqual(targetPath, target);
}
});

View file

@ -11,6 +11,7 @@ import "./mkdir_test.ts";
import "./make_temp_dir_test.ts";
import "./stat_test.ts";
import "./rename_test.ts";
import "./read_link_test.ts";
import "./blob_test.ts";
import "./timers_test.ts";
import "./symlink_test.ts";

View file

@ -56,6 +56,7 @@ pub extern "C" fn msg_from_js(i: *const isolate, buf: deno_buf) {
msg::Any::Remove => handle_remove,
msg::Any::ReadFile => handle_read_file,
msg::Any::Rename => handle_rename,
msg::Any::Readlink => handle_read_link,
msg::Any::Symlink => handle_symlink,
msg::Any::SetEnv => handle_set_env,
msg::Any::Stat => handle_stat,
@ -702,3 +703,31 @@ fn handle_symlink(i: *const isolate, base: &msg::Base) -> Box<Op> {
}()))
}
}
fn handle_read_link(_i: *const isolate, base: &msg::Base) -> Box<Op> {
let msg = base.msg_as_readlink().unwrap();
let cmd_id = base.cmd_id();
let name = String::from(msg.name().unwrap());
Box::new(futures::future::result(|| -> OpResult {
debug!("handle_read_link {}", name);
let path = fs::read_link(Path::new(&name))?;
let builder = &mut FlatBufferBuilder::new();
let path_off = builder.create_string(path.to_str().unwrap());
let msg = msg::ReadlinkRes::create(
builder,
&msg::ReadlinkResArgs {
path: Some(path_off),
..Default::default()
},
);
Ok(serialize_response(
cmd_id,
builder,
msg::BaseArgs {
msg: Some(msg.as_union_value()),
msg_type: msg::Any::ReadlinkRes,
..Default::default()
},
))
}()))
}

View file

@ -20,6 +20,8 @@ union Any {
ReadFileRes,
WriteFile,
Rename,
Readlink,
ReadlinkRes,
Symlink,
Stat,
StatRes,
@ -202,6 +204,14 @@ table Rename {
newpath: string;
}
table Readlink {
name: string;
}
table ReadlinkRes {
path: string;
}
table Symlink {
oldname: string;
newname: string;