Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: switch to local interfaces for Deno.Reader, WriterSync, Closer #196

Merged
merged 5 commits into from
Dec 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions mod.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ Deno.test("abort", async () => {
});

Deno.test("piping to stdin", async () => {
// Deno.Reader
// Reader
{
const bytes = new TextEncoder().encode("test\n");
const result =
Expand Down Expand Up @@ -768,7 +768,7 @@ Deno.test("piping to stdin", async () => {
}
});

Deno.test("spawning a command twice that has stdin set to a Deno.Reader should error", async () => {
Deno.test("spawning a command twice that has stdin set to a Reader should error", async () => {
const bytes = new TextEncoder().encode("test\n");
const command = $`deno eval "const b = new Uint8Array(4); await Deno.stdin.read(b); await Deno.stdout.write(b);"`
.stdin(new Buffer(bytes));
Expand Down
2 changes: 1 addition & 1 deletion mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export { FsFileWrapper, PathRef } from "./src/path.ts";
export type { ExpandGlobOptions, PathSymlinkOptions, SymlinkOptions, WalkEntry, WalkOptions } from "./src/path.ts";
export { CommandBuilder, CommandChild, CommandResult, KillSignal, KillSignalController } from "./src/command.ts";
export type { CommandContext, CommandHandler, CommandPipeReader, CommandPipeWriter } from "./src/command_handler.ts";
export type { ShellPipeReader, ShellPipeWriterKind } from "./src/pipes.ts";
export type { Closer, Reader, ShellPipeReader, ShellPipeWriterKind, WriterSync } from "./src/pipes.ts";
export type {
ConfirmOptions,
MultiSelectOption,
Expand Down
10 changes: 6 additions & 4 deletions src/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ import {
InheritStaticTextBypassWriter,
NullPipeWriter,
PipedBuffer,
Reader,
ShellPipeReader,
ShellPipeWriter,
ShellPipeWriterKind,
WriterSync,
} from "./pipes.ts";
import { parseCommand, spawn } from "./shell.ts";
import { isShowingProgressBars } from "./console/progress/interval.ts";
Expand All @@ -33,7 +35,7 @@ type BufferStdio = "inherit" | "null" | "streamed" | Buffer;

interface CommandBuilderState {
command: string | undefined;
stdin: "inherit" | "null" | Box<Deno.Reader | ReadableStream<Uint8Array> | "consumed">;
stdin: "inherit" | "null" | Box<Reader | ReadableStream<Uint8Array> | "consumed">;
combinedStdoutStderr: boolean;
stdoutKind: ShellPipeWriterKind;
stderrKind: ShellPipeWriterKind;
Expand Down Expand Up @@ -692,7 +694,7 @@ export function parseAndSpawnCommand(state: CommandBuilderState) {
}
return [stdoutBuffer, stderrBuffer, undefined] as const;

function getOutputBuffer(innerWriter: Deno.WriterSync, kind: ShellPipeWriterKind) {
function getOutputBuffer(innerWriter: WriterSync, kind: ShellPipeWriterKind) {
if (typeof kind === "object") {
return kind;
}
Expand All @@ -718,7 +720,7 @@ export function parseAndSpawnCommand(state: CommandBuilderState) {
}

function finalizeCommandResultBuffer(
buffer: PipedBuffer | "inherit" | "null" | CapturingBufferWriter | InheritStaticTextBypassWriter | Deno.WriterSync,
buffer: PipedBuffer | "inherit" | "null" | CapturingBufferWriter | InheritStaticTextBypassWriter | WriterSync,
): BufferStdio {
if (buffer instanceof CapturingBufferWriter) {
return buffer.getBuffer();
Expand All @@ -736,7 +738,7 @@ export function parseAndSpawnCommand(state: CommandBuilderState) {
}

function finalizeCommandResultBufferForError(
buffer: PipedBuffer | "inherit" | "null" | CapturingBufferWriter | InheritStaticTextBypassWriter | Deno.WriterSync,
buffer: PipedBuffer | "inherit" | "null" | CapturingBufferWriter | InheritStaticTextBypassWriter | WriterSync,
error: Error,
) {
if (buffer instanceof InheritStaticTextBypassWriter) {
Expand Down
5 changes: 3 additions & 2 deletions src/command_handler.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { ExecuteResult } from "./result.ts";
import type { KillSignal } from "./command.ts";
import { Reader, WriterSync } from "./pipes.ts";

/** Used to read from stdin. */
export type CommandPipeReader = "inherit" | "null" | Deno.Reader;
export type CommandPipeReader = "inherit" | "null" | Reader;

/** Used to write to stdout or stderr. */
export interface CommandPipeWriter extends Deno.WriterSync {
export interface CommandPipeWriter extends WriterSync {
writeSync(p: Uint8Array): number;
writeText(text: string): void;
writeLine(text: string): void;
Expand Down
2 changes: 1 addition & 1 deletion src/commands/cat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async function executeCat(context: CommandContext) {

for (const path of flags.paths) {
if (path === "-") { // read from stdin
if (typeof context.stdin === "object") { // stdin is a Deno.Reader
if (typeof context.stdin === "object") { // stdin is a Reader
while (true) {
const size = await context.stdin.read(buf);
if (!size || size === 0) break;
Expand Down
3 changes: 2 additions & 1 deletion src/common.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { logger } from "./console/mod.ts";
import { BufReader, path } from "./deps.ts";
import { Reader } from "./pipes.ts";

/**
* Delay used for certain actions.
Expand Down Expand Up @@ -216,7 +217,7 @@ export interface ShebangInfo {
}

const decoder = new TextDecoder();
export async function getExecutableShebang(reader: Deno.Reader): Promise<ShebangInfo | undefined> {
export async function getExecutableShebang(reader: Reader): Promise<ShebangInfo | undefined> {
const text = "#!/usr/bin/env ";
const buffer = new Uint8Array(text.length);
const bytesReadCount = await reader.read(buffer);
Expand Down
40 changes: 26 additions & 14 deletions src/pipes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,39 @@ import { Buffer, writeAllSync } from "./deps.ts";

const encoder = new TextEncoder();

export type ShellPipeReader = "inherit" | "null" | Deno.Reader;
export interface Reader {
read(p: Uint8Array): Promise<number | null>;
}

export interface WriterSync {
writeSync(p: Uint8Array): number;
}

export interface Closer {
close(): void;
}

export type ShellPipeReader = "inherit" | "null" | Reader;
/**
* The behaviour to use for a shell pipe.
* @value "inherit" - Sends the output directly to the current process' corresponding pipe (default).
* @value "null" - Does not pipe or redirect the pipe.
* @value "piped" - Captures the pipe without outputting.
* @value "inheritPiped" - Captures the pipe with outputting.
*/
export type ShellPipeWriterKind = "inherit" | "null" | "piped" | "inheritPiped" | Deno.WriterSync;
export type ShellPipeWriterKind = "inherit" | "null" | "piped" | "inheritPiped" | WriterSync;

export class NullPipeWriter implements Deno.WriterSync {
export class NullPipeWriter implements WriterSync {
writeSync(p: Uint8Array): number {
return p.length;
}
}

export class ShellPipeWriter implements Deno.WriterSync {
export class ShellPipeWriter implements WriterSync {
#kind: ShellPipeWriterKind;
#inner: Deno.WriterSync;
#inner: WriterSync;

constructor(kind: ShellPipeWriterKind, inner: Deno.WriterSync) {
constructor(kind: ShellPipeWriterKind, inner: WriterSync) {
this.#kind = kind;
this.#inner = inner;
}
Expand All @@ -45,11 +57,11 @@ export class ShellPipeWriter implements Deno.WriterSync {
}
}

export class CapturingBufferWriter implements Deno.WriterSync {
export class CapturingBufferWriter implements WriterSync {
#buffer: Buffer;
#innerWriter: Deno.WriterSync;
#innerWriter: WriterSync;

constructor(innerWriter: Deno.WriterSync, buffer: Buffer) {
constructor(innerWriter: WriterSync, buffer: Buffer) {
this.#innerWriter = innerWriter;
this.#buffer = buffer;
}
Expand All @@ -67,11 +79,11 @@ export class CapturingBufferWriter implements Deno.WriterSync {

const lineFeedCharCode = "\n".charCodeAt(0);

export class InheritStaticTextBypassWriter implements Deno.WriterSync {
export class InheritStaticTextBypassWriter implements WriterSync {
#buffer: Buffer;
#innerWriter: Deno.WriterSync;
#innerWriter: WriterSync;

constructor(innerWriter: Deno.WriterSync) {
constructor(innerWriter: WriterSync) {
this.#innerWriter = innerWriter;
this.#buffer = new Buffer();
}
Expand Down Expand Up @@ -99,11 +111,11 @@ export class InheritStaticTextBypassWriter implements Deno.WriterSync {
}
}

export interface PipedBufferListener extends Deno.WriterSync, Deno.Closer {
export interface PipedBufferListener extends WriterSync, Closer {
setError(err: Error): void;
}

export class PipedBuffer implements Deno.WriterSync {
export class PipedBuffer implements WriterSync {
#inner: Buffer | PipedBufferListener;
#hasSet = false;

Expand Down
6 changes: 3 additions & 3 deletions src/shell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { CommandContext, CommandHandler } from "./command_handler.ts";
import { getExecutableShebangFromPath, ShebangInfo } from "./common.ts";
import { DenoWhichRealEnvironment, fs, path, which } from "./deps.ts";
import { wasmInstance } from "./lib/mod.ts";
import { ShellPipeReader, ShellPipeWriter, ShellPipeWriterKind } from "./pipes.ts";
import { Reader, ShellPipeReader, ShellPipeWriter, ShellPipeWriterKind, WriterSync } from "./pipes.ts";
import { EnvChange, ExecuteResult, getAbortedResult, resultFromCode } from "./result.ts";

export interface SequentialList {
Expand Down Expand Up @@ -670,7 +670,7 @@ async function executeCommandArgs(commandArgs: string[], context: Context): Prom
await pipeReaderToWriterSync(readable, writer, new AbortController().signal);
}

async function pipeReaderToWriter(reader: Deno.Reader, writable: WritableStream<Uint8Array>, signal: AbortSignal) {
async function pipeReaderToWriter(reader: Reader, writable: WritableStream<Uint8Array>, signal: AbortSignal) {
const abortedPromise = new Promise<void>((resolve) => {
signal.addEventListener("abort", listener);
function listener() {
Expand All @@ -695,7 +695,7 @@ async function executeCommandArgs(commandArgs: string[], context: Context): Prom

async function pipeReaderToWriterSync(
readable: ReadableStream<Uint8Array>,
writer: Deno.WriterSync,
writer: WriterSync,
signal: AbortSignal,
) {
const reader = readable.getReader();
Expand Down