1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-25 15:29:32 -05:00

Add deno.truncate (#805)

This commit is contained in:
ztplz 2018-10-01 03:06:20 +08:00 committed by Ryan Dahl
parent f51903f773
commit 062b22fe56
7 changed files with 147 additions and 0 deletions

View file

@ -96,6 +96,7 @@ ts_sources = [
"js/text_encoding.ts",
"js/timers.ts",
"js/trace.ts",
"js/truncate.ts",
"js/types.ts",
"js/util.ts",
"js/v8_source_maps.ts",

View file

@ -17,5 +17,6 @@ export { ErrorKind, DenoError } from "./errors";
export { libdeno } from "./libdeno";
export { arch, platform } from "./platform";
export { trace } from "./trace";
export { truncateSync, truncate } from "./truncate";
export { setGlobalTimeout } from "./timers";
export const args: string[] = [];

42
js/truncate.ts Normal file
View file

@ -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";
/**
* Truncates or extends the specified file synchronously,
* updating the size of this file to become size.
*
* import { truncateSync } from "deno";
*
* truncateSync("hello.txt", 10);
*/
export function truncateSync(name: string, len?: number): void {
dispatch.sendSync(...req(name, len));
}
/**
* Truncates or extends the specified file,
* updating the size of this file to become size.
*
* import { truncate } from "deno";
*
* await truncate("hello.txt", 10);
*/
export async function truncate(name: string, len?: number): Promise<void> {
await dispatch.sendAsync(...req(name, len));
}
function req(
name: string,
len?: number
): [flatbuffers.Builder, fbs.Any, flatbuffers.Offset] {
const builder = new flatbuffers.Builder();
const name_ = builder.createString(name);
len = len && len > 0 ? Math.floor(len) : 0;
fbs.Truncate.startTruncate(builder);
fbs.Truncate.addName(builder, name_);
fbs.Truncate.addLen(builder, len);
const msg = fbs.Truncate.endTruncate(builder);
return [builder, fbs.Any.Truncate, msg];
}

73
js/truncate_test.ts Normal file
View file

@ -0,0 +1,73 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
import { testPerm, assertEqual } from "./test_util.ts";
import * as deno from "deno";
function readDataSync(name: string): string {
const data = deno.readFileSync(name);
const decoder = new TextDecoder("utf-8");
const text = decoder.decode(data);
return text;
}
async function readData(name: string): Promise<string> {
const data = await deno.readFile(name);
const decoder = new TextDecoder("utf-8");
const text = decoder.decode(data);
return text;
}
testPerm({ write: true }, function truncateSyncSuccess() {
const enc = new TextEncoder();
const d = enc.encode("Hello");
const filename = deno.makeTempDirSync() + "/test_truncateSync.txt";
deno.writeFileSync(filename, d);
deno.truncateSync(filename, 20);
let data = readDataSync(filename);
assertEqual(data.length, 20);
deno.truncateSync(filename, 5);
data = readDataSync(filename);
assertEqual(data.length, 5);
deno.truncateSync(filename, -5);
data = readDataSync(filename);
assertEqual(data.length, 0);
deno.removeSync(filename);
});
testPerm({ write: true }, async function truncateSuccess() {
const enc = new TextEncoder();
const d = enc.encode("Hello");
const filename = deno.makeTempDirSync() + "/test_truncate.txt";
await deno.writeFile(filename, d);
await deno.truncate(filename, 20);
let data = await readData(filename);
assertEqual(data.length, 20);
await deno.truncate(filename, 5);
data = await readData(filename);
assertEqual(data.length, 5);
await deno.truncate(filename, -5);
data = await readData(filename);
assertEqual(data.length, 0);
await deno.remove(filename);
});
testPerm({ write: false }, function truncateSyncPerm() {
let err;
try {
deno.mkdirSync("/test_truncateSyncPermission.txt");
} catch (e) {
err = e;
}
assertEqual(err.kind, deno.ErrorKind.PermissionDenied);
assertEqual(err.name, "PermissionDenied");
});
testPerm({ write: false }, async function truncatePerm() {
let err;
try {
await deno.mkdir("/test_truncatePermission.txt");
} catch (e) {
err = e;
}
assertEqual(err.kind, deno.ErrorKind.PermissionDenied);
assertEqual(err.name, "PermissionDenied");
});

View file

@ -19,5 +19,6 @@ import "./symlink_test.ts";
import "./platform_test.ts";
import "./text_encoding_test.ts";
import "./trace_test.ts";
import "./truncate_test.ts";
import "./v8_source_maps_test.ts";
import "../website/app_test.js";

View file

@ -77,6 +77,7 @@ pub fn msg_from_js(
msg::Any::Symlink => handle_symlink,
msg::Any::SetEnv => handle_set_env,
msg::Any::Stat => handle_stat,
msg::Any::Truncate => handle_truncate,
msg::Any::WriteFile => handle_write_file,
msg::Any::Exit => handle_exit,
_ => panic!(format!(
@ -977,3 +978,25 @@ fn handle_read_link(
))
})
}
fn handle_truncate(
state: Arc<IsolateState>,
base: &msg::Base,
data: &'static mut [u8],
) -> Box<Op> {
assert_eq!(data.len(), 0);
if !state.flags.allow_write {
return odd_future(permission_denied());
}
let msg = base.msg_as_truncate().unwrap();
let filename = String::from(msg.name().unwrap());
let len = msg.len();
blocking!(base.sync(), || {
debug!("handle_truncate {} {}", filename, len);
let f = fs::OpenOptions::new().write(true).open(&filename)?;
f.set_len(len as u64)?;
Ok(empty_buf())
})
}

View file

@ -27,6 +27,7 @@ union Any {
Stat,
StatRes,
SetEnv,
Truncate,
Open,
OpenRes,
Read,
@ -247,6 +248,11 @@ table StatRes {
has_mode: bool; // false on windows
}
table Truncate {
name: string;
len: uint;
}
table WriteFileSync {
filename: string;
data: [ubyte];