mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
Add cwd() and chdir() (#907)
This commit is contained in:
parent
d92c99eaba
commit
bbf88c5295
7 changed files with 156 additions and 5 deletions
2
BUILD.gn
2
BUILD.gn
|
@ -72,6 +72,7 @@ ts_sources = [
|
|||
"js/console.ts",
|
||||
"js/copy_file.ts",
|
||||
"js/deno.ts",
|
||||
"js/dir.ts",
|
||||
"js/dispatch.ts",
|
||||
"js/dom_types.ts",
|
||||
"js/errors.ts",
|
||||
|
@ -107,7 +108,6 @@ ts_sources = [
|
|||
"js/util.ts",
|
||||
"js/v8_source_maps.ts",
|
||||
"js/write_file.ts",
|
||||
|
||||
"tsconfig.json",
|
||||
|
||||
# Listing package.json and yarn.lock as sources ensures the bundle is rebuilt
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Public deno module.
|
||||
/// <amd-module name="deno"/>
|
||||
export { env, exit } from "./os";
|
||||
export { chdir, cwd } from "./dir";
|
||||
export { File, open, stdin, stdout, stderr, read, write, close } from "./files";
|
||||
export {
|
||||
copy,
|
||||
|
|
37
js/dir.ts
Normal file
37
js/dir.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
||||
import * as msg from "gen/msg_generated";
|
||||
import { assert } from "./util";
|
||||
import { flatbuffers } from "flatbuffers";
|
||||
import { sendSync } from "./dispatch";
|
||||
|
||||
/**
|
||||
* cwd() Return a string representing the current working directory.
|
||||
* If the current directory can be reached via multiple paths
|
||||
* (due to symbolic links), cwd() may return
|
||||
* any one of them.
|
||||
* throws NotFound exception if directory not available
|
||||
*/
|
||||
export function cwd(): string {
|
||||
const builder = new flatbuffers.Builder(0);
|
||||
msg.Cwd.startCwd(builder);
|
||||
const inner = msg.Cwd.endCwd(builder);
|
||||
const baseRes = sendSync(builder, msg.Any.Cwd, inner);
|
||||
assert(baseRes != null);
|
||||
assert(msg.Any.CwdRes === baseRes!.innerType());
|
||||
const res = new msg.CwdRes();
|
||||
assert(baseRes!.inner(res) != null);
|
||||
return res.cwd()!;
|
||||
}
|
||||
|
||||
/**
|
||||
* chdir() Change the current working directory to path.
|
||||
* throws NotFound exception if directory not available
|
||||
*/
|
||||
export function chdir(directory: string): void {
|
||||
const builder = new flatbuffers.Builder();
|
||||
const directory_ = builder.createString(directory);
|
||||
msg.Chdir.startChdir(builder);
|
||||
msg.Chdir.addDirectory(builder, directory_);
|
||||
const inner = msg.Chdir.endChdir(builder);
|
||||
sendSync(builder, msg.Any.Chdir, inner);
|
||||
}
|
54
js/dir_test.ts
Normal file
54
js/dir_test.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
import { test, testPerm, assert, assertEqual } from "./test_util.ts";
|
||||
import * as deno from "deno";
|
||||
|
||||
test(function dirCwdNotNull() {
|
||||
assert(deno.cwd() != null);
|
||||
});
|
||||
|
||||
testPerm({ write: true }, function dirCwdChdirSuccess() {
|
||||
const initialdir = deno.cwd();
|
||||
const path = deno.makeTempDirSync();
|
||||
deno.chdir(path);
|
||||
const current = deno.cwd();
|
||||
if (deno.platform.os === "mac") {
|
||||
assertEqual(current, "/private" + path);
|
||||
} else {
|
||||
assertEqual(current, path);
|
||||
}
|
||||
deno.chdir(initialdir);
|
||||
});
|
||||
|
||||
testPerm({ write: true }, function dirCwdError() {
|
||||
// excluding windows since it throws resource busy, while removeSync
|
||||
if (["linux", "mac"].includes(deno.platform.os)) {
|
||||
const initialdir = deno.cwd();
|
||||
const path = deno.makeTempDirSync();
|
||||
deno.chdir(path);
|
||||
deno.removeSync(path);
|
||||
try {
|
||||
deno.cwd();
|
||||
throw Error("current directory removed, should throw error");
|
||||
} catch (err) {
|
||||
if (err instanceof deno.DenoError) {
|
||||
console.log(err.name === "NotFound");
|
||||
} else {
|
||||
throw Error("raised different exception");
|
||||
}
|
||||
}
|
||||
deno.chdir(initialdir);
|
||||
}
|
||||
});
|
||||
|
||||
testPerm({ write: true }, function dirChdirError() {
|
||||
const path = deno.makeTempDirSync() + "test";
|
||||
try {
|
||||
deno.chdir(path);
|
||||
throw Error("directory not available, should throw error");
|
||||
} catch (err) {
|
||||
if (err instanceof deno.DenoError) {
|
||||
console.log(err.name === "NotFound");
|
||||
} else {
|
||||
throw Error("raised different exception");
|
||||
}
|
||||
}
|
||||
});
|
|
@ -11,6 +11,7 @@ import "./read_dir_test.ts";
|
|||
import "./write_file_test.ts";
|
||||
import "./copy_file_test.ts";
|
||||
import "./mkdir_test.ts";
|
||||
import "./dir_test";
|
||||
import "./make_temp_dir_test.ts";
|
||||
import "./stat_test.ts";
|
||||
import "./rename_test.ts";
|
||||
|
|
13
src/msg.fbs
13
src/msg.fbs
|
@ -41,6 +41,9 @@ union Any {
|
|||
Accept,
|
||||
Dial,
|
||||
NewConn,
|
||||
Chdir,
|
||||
Cwd,
|
||||
CwdRes,
|
||||
Metrics,
|
||||
MetricsRes,
|
||||
}
|
||||
|
@ -93,6 +96,12 @@ enum ErrorKind: byte {
|
|||
HttpOther,
|
||||
}
|
||||
|
||||
table Cwd {}
|
||||
|
||||
table CwdRes {
|
||||
cwd: string;
|
||||
}
|
||||
|
||||
table Base {
|
||||
cmd_id: uint32;
|
||||
sync: bool = true; // TODO(ry) Change default to false.
|
||||
|
@ -135,6 +144,10 @@ table CodeCache {
|
|||
output_code: string;
|
||||
}
|
||||
|
||||
table Chdir {
|
||||
directory: string;
|
||||
}
|
||||
|
||||
table SetTimeout {
|
||||
timeout: double;
|
||||
}
|
||||
|
|
53
src/ops.rs
53
src/ops.rs
|
@ -101,6 +101,8 @@ pub fn dispatch(
|
|||
msg::Any::Listen => op_listen,
|
||||
msg::Any::Accept => op_accept,
|
||||
msg::Any::Dial => op_dial,
|
||||
msg::Any::Chdir => op_chdir,
|
||||
msg::Any::Cwd => op_cwd,
|
||||
msg::Any::Metrics => op_metrics,
|
||||
_ => panic!(format!(
|
||||
"Unhandled message {}",
|
||||
|
@ -110,8 +112,7 @@ pub fn dispatch(
|
|||
op_creator(isolate.state.clone(), &base, data)
|
||||
};
|
||||
|
||||
let boxed_op = Box::new(
|
||||
op.or_else(move |err: DenoError| -> DenoResult<Buf> {
|
||||
let boxed_op = Box::new(op.or_else(move |err: DenoError| -> DenoResult<Buf> {
|
||||
debug!("op err {}", err);
|
||||
// No matter whether we got an Err or Ok, we want a serialized message to
|
||||
// send back. So transform the DenoError into a deno_buf.
|
||||
|
@ -143,8 +144,7 @@ pub fn dispatch(
|
|||
)
|
||||
};
|
||||
Ok(buf)
|
||||
}),
|
||||
);
|
||||
}));
|
||||
|
||||
debug!(
|
||||
"msg_from_js {} sync {}",
|
||||
|
@ -283,6 +283,20 @@ fn op_code_cache(
|
|||
}()))
|
||||
}
|
||||
|
||||
fn op_chdir(
|
||||
_state: Arc<IsolateState>,
|
||||
base: &msg::Base,
|
||||
data: &'static mut [u8],
|
||||
) -> Box<Op> {
|
||||
assert_eq!(data.len(), 0);
|
||||
let inner = base.inner_as_chdir().unwrap();
|
||||
let directory = inner.directory().unwrap();
|
||||
Box::new(futures::future::result(|| -> OpResult {
|
||||
let _result = std::env::set_current_dir(&directory)?;
|
||||
Ok(empty_buf())
|
||||
}()))
|
||||
}
|
||||
|
||||
fn op_set_timeout(
|
||||
isolate: &mut Isolate,
|
||||
base: &msg::Base,
|
||||
|
@ -811,6 +825,37 @@ fn get_mode(_perm: fs::Permissions) -> u32 {
|
|||
0
|
||||
}
|
||||
|
||||
fn op_cwd(
|
||||
_state: Arc<IsolateState>,
|
||||
base: &msg::Base,
|
||||
data: &'static mut [u8],
|
||||
) -> Box<Op> {
|
||||
assert_eq!(data.len(), 0);
|
||||
let cmd_id = base.cmd_id();
|
||||
Box::new(futures::future::result(|| -> OpResult {
|
||||
let path = std::env::current_dir()?;
|
||||
let builder = &mut FlatBufferBuilder::new();
|
||||
let cwd =
|
||||
builder.create_string(&path.into_os_string().into_string().unwrap());
|
||||
let inner = msg::CwdRes::create(
|
||||
builder,
|
||||
&msg::CwdResArgs {
|
||||
cwd: Some(cwd),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
Ok(serialize_response(
|
||||
cmd_id,
|
||||
builder,
|
||||
msg::BaseArgs {
|
||||
inner: Some(inner.as_union_value()),
|
||||
inner_type: msg::Any::CwdRes,
|
||||
..Default::default()
|
||||
},
|
||||
))
|
||||
}()))
|
||||
}
|
||||
|
||||
fn op_stat(
|
||||
_config: Arc<IsolateState>,
|
||||
base: &msg::Base,
|
||||
|
|
Loading…
Reference in a new issue