diff --git a/BUILD.gn b/BUILD.gn
index 839e904bec..180519d6e6 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -199,6 +199,7 @@ run_node("gen_declarations") {
"js/mkdir.ts",
"js/os.ts",
"js/read_file.ts",
+ "js/rename.ts",
"js/remove.ts",
"js/stat.ts",
"js/text_encoding.ts",
@@ -242,6 +243,7 @@ run_node("bundle") {
"js/os.ts",
"js/plugins.d.ts",
"js/read_file.ts",
+ "js/rename.ts",
"js/remove.ts",
"js/stat.ts",
"js/text_encoding.ts",
diff --git a/js/deno.ts b/js/deno.ts
index 3d0352a809..6f71ee4991 100644
--- a/js/deno.ts
+++ b/js/deno.ts
@@ -1,10 +1,15 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
// Public deno module.
///
-export { env, exit, makeTempDirSync, renameSync } from "./os";
+export {
+ env,
+ exit,
+ makeTempDirSync
+} from "./os";
export { mkdirSync, mkdir } from "./mkdir";
export { removeSync, remove, removeAllSync, removeAll } from "./remove";
export { readFileSync, readFile } from "./read_file";
+export { renameSync, rename } from "./rename";
export { FileInfo, statSync, lstatSync, stat, lstat } from "./stat";
export { writeFileSync, writeFile } from "./write_file";
export { ErrorKind, DenoError } from "./errors";
diff --git a/js/os.ts b/js/os.ts
index 264cdcbaff..d73865c065 100644
--- a/js/os.ts
+++ b/js/os.ts
@@ -164,22 +164,3 @@ export function env(): { [index: string]: string } {
// TypeScript cannot track assertion above, therefore not null assertion
return createEnv(res);
}
-
-/**
- * Renames (moves) oldpath to newpath.
- * import { renameSync } from "deno";
- * const oldpath = 'from/path';
- * const newpath = 'to/path';
- *
- * renameSync(oldpath, newpath);
- */
-export function renameSync(oldpath: string, newpath: string): void {
- const builder = new flatbuffers.Builder();
- const _oldpath = builder.createString(oldpath);
- const _newpath = builder.createString(newpath);
- fbs.RenameSync.startRenameSync(builder);
- fbs.RenameSync.addOldpath(builder, _oldpath);
- fbs.RenameSync.addNewpath(builder, _newpath);
- const msg = fbs.RenameSync.endRenameSync(builder);
- sendSync(builder, fbs.Any.RenameSync, msg);
-}
diff --git a/js/os_test.ts b/js/os_test.ts
index c0198095cd..61227a3b10 100644
--- a/js/os_test.ts
+++ b/js/os_test.ts
@@ -60,40 +60,3 @@ test(function makeTempDirSyncPerm() {
assertEqual(err.kind, deno.ErrorKind.PermissionDenied);
assertEqual(err.name, "PermissionDenied");
});
-
-testPerm({ write: true }, function renameSync() {
- const testDir = deno.makeTempDirSync() + "/test-rename";
- const oldpath = testDir + "/oldpath";
- const newpath = testDir + "/newpath";
- deno.mkdirSync(oldpath);
- deno.renameSync(oldpath, newpath);
- const newPathInfo = deno.statSync(newpath);
- assert(newPathInfo.isDirectory());
-
- let caughtErr = false;
- let oldPathInfo;
-
- try {
- oldPathInfo = deno.statSync(oldpath);
- } catch (err) {
- caughtErr = true;
- assertEqual(err.kind, deno.ErrorKind.NotFound);
- assertEqual(err.name, "NotFound");
- }
-
- assert(caughtErr);
- assertEqual(oldPathInfo, undefined);
-});
-
-test(function renameSyncPerm() {
- let err;
- try {
- const oldpath = "/oldbaddir";
- const newpath = "/newbaddir";
- deno.renameSync(oldpath, newpath);
- } catch (err_) {
- err = err_;
- }
- assertEqual(err.kind, deno.ErrorKind.PermissionDenied);
- assertEqual(err.name, "PermissionDenied");
-});
diff --git a/js/rename.ts b/js/rename.ts
new file mode 100644
index 0000000000..241e274908
--- /dev/null
+++ b/js/rename.ts
@@ -0,0 +1,42 @@
+// Copyright 2018 the Deno authors. All rights reserved. MIT license.
+import * as fbs from "gen/msg_generated";
+import { flatbuffers } from "flatbuffers";
+import * as dispatch from "./dispatch";
+
+/**
+ * Synchronously renames (moves) oldpath to newpath. If newpath already exists
+ * and is not a directory, Rename replaces it. OS-specific restrictions may
+ * apply when oldpath and newpath are in different directories.
+ *
+ * import { renameSync } from "deno";
+ * renameSync("old/path", "new/path");
+ */
+export function renameSync(oldpath: string, newpath: string): void {
+ dispatch.sendSync(...req(oldpath, newpath));
+}
+
+/**
+ * Renames (moves) oldpath to newpath. If newpath already exists
+ * and is not a directory, Rename replaces it. OS-specific restrictions may
+ * apply when oldpath and newpath are in different directories.
+ *
+ * import { rename } from "deno";
+ * await rename("old/path", "new/path");
+ */
+export async function rename(oldpath: string, newpath: string): Promise {
+ await dispatch.sendAsync(...req(oldpath, newpath));
+}
+
+function req(
+ oldpath: string,
+ newpath: string
+): [flatbuffers.Builder, fbs.Any, flatbuffers.Offset] {
+ const builder = new flatbuffers.Builder();
+ const oldpath_ = builder.createString(oldpath);
+ const newpath_ = builder.createString(newpath);
+ fbs.Rename.startRename(builder);
+ fbs.Rename.addOldpath(builder, oldpath_);
+ fbs.Rename.addNewpath(builder, newpath_);
+ const msg = fbs.Rename.endRename(builder);
+ return [builder, fbs.Any.Rename, msg];
+}
diff --git a/js/rename_test.ts b/js/rename_test.ts
new file mode 100644
index 0000000000..450760dae6
--- /dev/null
+++ b/js/rename_test.ts
@@ -0,0 +1,60 @@
+// 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 renameSyncSuccess() {
+ const testDir = deno.makeTempDirSync() + "/test-rename-sync";
+ const oldpath = testDir + "/oldpath";
+ const newpath = testDir + "/newpath";
+ deno.mkdirSync(oldpath);
+ deno.renameSync(oldpath, newpath);
+ const newPathInfo = deno.statSync(newpath);
+ assert(newPathInfo.isDirectory());
+
+ let caughtErr = false;
+ let oldPathInfo;
+
+ try {
+ oldPathInfo = deno.statSync(oldpath);
+ } catch (e) {
+ caughtErr = true;
+ assertEqual(e.kind, deno.ErrorKind.NotFound);
+ }
+ assert(caughtErr);
+ assertEqual(oldPathInfo, undefined);
+});
+
+testPerm({ write: false }, function renameSyncPerm() {
+ let err;
+ try {
+ const oldpath = "/oldbaddir";
+ const newpath = "/newbaddir";
+ deno.renameSync(oldpath, newpath);
+ } catch (e) {
+ err = e;
+ }
+ assertEqual(err.kind, deno.ErrorKind.PermissionDenied);
+ assertEqual(err.name, "PermissionDenied");
+});
+
+testPerm({ write: true }, async function renameSuccess() {
+ const testDir = deno.makeTempDirSync() + "/test-rename";
+ const oldpath = testDir + "/oldpath";
+ const newpath = testDir + "/newpath";
+ deno.mkdirSync(oldpath);
+ await deno.rename(oldpath, newpath);
+ const newPathInfo = deno.statSync(newpath);
+ assert(newPathInfo.isDirectory());
+
+ let caughtErr = false;
+ let oldPathInfo;
+
+ try {
+ oldPathInfo = deno.statSync(oldpath);
+ } catch (e) {
+ caughtErr = true;
+ assertEqual(e.kind, deno.ErrorKind.NotFound);
+ }
+ assert(caughtErr);
+ assertEqual(oldPathInfo, undefined);
+});
diff --git a/js/unit_tests.ts b/js/unit_tests.ts
index 88e6fb9d94..b406b63d08 100644
--- a/js/unit_tests.ts
+++ b/js/unit_tests.ts
@@ -9,3 +9,4 @@ import "./read_file_test.ts";
import "./write_file_test.ts";
import "./mkdir_test.ts";
import "./stat_test.ts";
+import "./rename_test.ts";
diff --git a/src/handlers.rs b/src/handlers.rs
index 681f18812b..09b4e299a8 100644
--- a/src/handlers.rs
+++ b/src/handlers.rs
@@ -55,7 +55,7 @@ pub extern "C" fn msg_from_js(d: *const DenoC, buf: deno_buf) {
msg::Any::Mkdir => handle_mkdir,
msg::Any::Remove => handle_remove,
msg::Any::ReadFile => handle_read_file,
- msg::Any::RenameSync => handle_rename_sync,
+ msg::Any::Rename => handle_rename,
msg::Any::SetEnv => handle_set_env,
msg::Any::Stat => handle_stat,
msg::Any::WriteFile => handle_write_file,
@@ -633,15 +633,14 @@ fn handle_timer_clear(d: *const DenoC, base: &msg::Base) -> Box {
ok_future(None)
}
-fn handle_rename_sync(d: *const DenoC, base: &msg::Base) -> Box {
+fn handle_rename(d: *const DenoC, base: &msg::Base) -> Box {
let deno = from_c(d);
if !deno.flags.allow_write {
- return Box::new(futures::future::err(permission_denied()));
- };
- let msg = base.msg_as_rename_sync().unwrap();
+ return odd_future(permission_denied());
+ }
+ let msg = base.msg_as_rename().unwrap();
let oldpath = String::from(msg.oldpath().unwrap());
let newpath = String::from(msg.newpath().unwrap());
- // TODO use blocking()
Box::new(futures::future::result(|| -> OpResult {
debug!("handle_rename {} {}", oldpath, newpath);
fs::rename(Path::new(&oldpath), Path::new(&newpath))?;
diff --git a/src/msg.fbs b/src/msg.fbs
index 458f5f437b..c630fec9d9 100644
--- a/src/msg.fbs
+++ b/src/msg.fbs
@@ -19,7 +19,7 @@ union Any {
ReadFile,
ReadFileRes,
WriteFile,
- RenameSync,
+ Rename,
Stat,
StatRes,
SetEnv,
@@ -194,7 +194,7 @@ table WriteFile {
// perm specified by https://godoc.org/os#FileMode
}
-table RenameSync {
+table Rename {
oldpath: string;
newpath: string;
}