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:
parent
f51903f773
commit
062b22fe56
7 changed files with 147 additions and 0 deletions
1
BUILD.gn
1
BUILD.gn
|
@ -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",
|
||||
|
|
|
@ -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
42
js/truncate.ts
Normal 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
73
js/truncate_test.ts
Normal 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");
|
||||
});
|
|
@ -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";
|
||||
|
|
|
@ -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())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in a new issue