Skip to content

Commit

Permalink
Lint with deno 1.33
Browse files Browse the repository at this point in the history
  • Loading branch information
mxcl committed Apr 29, 2023
1 parent f3e2d03 commit 12c9669
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 57 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</p>


# tea/cli 0.30.0
# tea/cli 0.31.0

`tea` puts the whole open source ecosystem at your fingertips:

Expand Down
20 changes: 10 additions & 10 deletions src/hooks/useRun.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Path from "path"
import { isArray } from "is_what"

export interface RunOptions extends Omit<Deno.RunOptions, 'cmd'|'cwd'|'stdout'|'stderr'|'stdin'> {
export interface RunOptions extends Omit<Deno.CommandOptions, 'args'|'cwd'|'stdout'|'stderr'|'stdin'> {
cmd: (string | Path)[] | Path
cwd?: (string | Path)
clearEnv?: boolean //NOTE might not be cross platform!
Expand All @@ -21,33 +21,33 @@ export default async function useRun({ spin, ...opts }: RunOptions) {
const cwd = opts.cwd?.toString()
console.verbose({ cwd, ...opts, cmd })

const stdio = { stdout: 'inherit', stderr: 'inherit', stdin: 'inherit' } as Pick<Deno.RunOptions, 'stdout'|'stderr'|'stdin'>
const stdio = { stdout: 'inherit', stderr: 'inherit', stdin: 'inherit' } as Pick<Deno.CommandOptions, 'stdout'|'stderr'|'stdin'>
if (spin) {
stdio.stderr = stdio.stdout = 'piped'
}

let proc: Deno.Process | undefined
let proc: Deno.ChildProcess | undefined
try {
proc = _internals.nativeRun({ ...opts, cmd, cwd, ...stdio })
const exit = await proc.status()
proc = _internals.nativeRun(cmd.shift()!, { ...opts, args: cmd, cwd, ...stdio }).spawn()
const exit = await proc.status
console.verbose({ exit })
if (!exit.success) throw new RunError(exit.code, cmd)
} catch (err) {
if (spin && proc) {
//FIXME this doesn’t result in the output being correctly interlaced
// ie. stderr and stdout may (probably) have been output interleaved rather than sequentially
const decode = (() => { const e = new TextDecoder(); return e.decode.bind(e) })()
console.error(decode(await proc.output()))
console.error(decode(await proc.stderrOutput()))
console.error(decode((await proc.output()).stdout))
console.error(decode((await proc.output()).stderr))
}

err.cmd = cmd // help us out since deno-devs don’t want to
throw err
} finally {
proc?.close()
}
}

const nativeRun = (runOptions: Deno.RunOptions) => Deno.run(runOptions)

const nativeRun = (cmd: string, opts: Deno.CommandOptions) => new Deno.Command(cmd, opts)

// _internals are used for testing
export const _internals = {
Expand Down
8 changes: 4 additions & 4 deletions src/vendor/Path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,12 +317,12 @@ export default class Path {

let opts = "-s"
if (force) opts += "fn"
const status = await Deno.run({
cmd: ["/bin/ln", opts, src, dst],
const status = await new Deno.Command("/bin/ln", {
args: [opts, src, dst],
cwd: this.string
}).status()
}).spawn().status

if (status.code != 0) throw new Error(`failed: cd ${this} && ln -sf ${src} ${dst}`)
if (!status.success) throw new Error(`failed: cd ${this} && ln -sf ${src} ${dst}`)

return to
}
Expand Down
35 changes: 18 additions & 17 deletions tests/functional/exec.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,54 +8,55 @@ Deno.test("exec", { sanitizeResources: false, sanitizeOps: false }, async () =>

const useRunSpy = spy(useRunInternals, "nativeRun")
try {
await run(["node", "--version"])
await run(["node", "--version"])
} finally {
useRunSpy.restore()
}

assertEquals(useRunSpy.calls[0].args[0].cmd, ["node", "--version"], "should have run node --version")
const foo = [useRunSpy.calls[0].args[0], ...useRunSpy.calls[0].args[1].args!]
assertEquals(foo, ["node", "--version"], "should have run node --version")
})

Deno.test("forward env to exec", { sanitizeResources: false, sanitizeOps: false }, async () => {
Deno.test("forward env to exec", { sanitizeResources: false, sanitizeOps: false }, async () => {
const {run, TEA_PREFIX, useRunInternals } = await createTestHarness()

const useRunSpy = spy(useRunInternals, "nativeRun")
try {
await run(["sh", "-c", "echo $TEA_PREFIX"])
await run(["sh", "-c", "echo $TEA_PREFIX"])
} finally {
useRunSpy.restore()
}

assertEquals(useRunSpy.calls[0].args[0].env?.["TEA_PREFIX"], TEA_PREFIX.string)
assertEquals(useRunSpy.calls[0].args[1].env?.["TEA_PREFIX"], TEA_PREFIX.string)
})

Deno.test("exec run errors", { sanitizeResources: false, sanitizeOps: false }, async test => {
const tests = [
{
name: "exit error",
procStatus: (): Promise<Deno.ProcessStatus> => Promise.resolve({success: false, code: 123}),
procStatus: (): Promise<Deno.CommandStatus> => Promise.resolve({success: false, code: 123, signal: null}),
expectedErr: "exiting with code: 123",
},
},
{
name: "normal error",
procStatus: (): Promise<Deno.ProcessStatus> => Promise.reject(new Error("test error")),
procStatus: (): Promise<Deno.CommandStatus> => Promise.reject(new Error("test error")),
expectedErr: "exiting with code: 1",
},
},
{
name: "tea error",
procStatus: (): Promise<Deno.ProcessStatus> => Promise.reject(new TeaError("confused: interpreter", {})),
procStatus: (): Promise<Deno.CommandStatus> => Promise.reject(new TeaError("confused: interpreter", {})),
expectedErr: "exiting with code: 1",
},
},
{
name: "not found",
procStatus: (): Promise<Deno.ProcessStatus> => Promise.reject(new Deno.errors.NotFound()),
procStatus: (): Promise<Deno.CommandStatus> => Promise.reject(new Deno.errors.NotFound()),
expectedErr: "exiting with code: 127",
},
},
{
name: "permission denied",
procStatus: (): Promise<Deno.ProcessStatus> => Promise.reject(new Deno.errors.PermissionDenied()),
procStatus: (): Promise<Deno.CommandStatus> => Promise.reject(new Deno.errors.PermissionDenied()),
expectedErr: "exiting with code: 127",
},
},
]

for (const { name, procStatus, expectedErr } of tests) {
Expand All @@ -66,7 +67,7 @@ Deno.test("exec run errors", { sanitizeResources: false, sanitizeOps: false }, a
const useRunStub = stub(useRunInternals, "nativeRun", returnsNext([mockProc]))
await assertRejects(async () => {
try {
await run(["node", "--version"])
await run(["node", "--version"])
} finally {
useRunStub.restore()
}
Expand All @@ -76,7 +77,7 @@ Deno.test("exec run errors", { sanitizeResources: false, sanitizeOps: false }, a
})

Deno.test("exec forkbomb protector", { sanitizeResources: false, sanitizeOps: false }, async () => {
const {run } = await createTestHarness()
const { run } = await createTestHarness()
await assertRejects(
() => run(["sh", "-c", "echo $TEA_PREFIX"], { env: {TEA_FORK_BOMB_PROTECTOR: "21" }}),
"FORK BOMB KILL SWITCH ACTIVATED")
Expand Down
23 changes: 11 additions & 12 deletions tests/functional/repl.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { stub, returnsNext } from "deno/testing/mock.ts"
import { ExitError } from "types"
import { createTestHarness, newMockProcess } from "./testUtils.ts"

Deno.test("should enter repl - sh", { sanitizeResources: false, sanitizeOps: false }, async test => {
Deno.test("should enter repl - sh", { sanitizeResources: false, sanitizeOps: false }, async test => {
const tests = [
{
{
shell: "/bin/sh",
expectedCmd: ["/bin/sh", "-i"],
expectedEnv: {"PS1": "\\[\\033[38;5;86m\\]tea\\[\\033[0m\\] %~ "},
Expand Down Expand Up @@ -41,14 +41,15 @@ Deno.test("should enter repl - sh", { sanitizeResources: false, sanitizeOps: fal
const useRunStub = stub(useRunInternals, "nativeRun", returnsNext([newMockProcess()]))

try {
await run(["sh"], { env: { SHELL: shell } })
await run(["sh"], { env: { SHELL: shell } })
} finally {
useRunStub.restore()
}

assertEquals(useRunStub.calls[0].args[0].cmd, expectedCmd)
const foo = [useRunStub.calls[0].args[0], ...useRunStub.calls[0].args[1].args!]
assertEquals(foo, expectedCmd)

const { env } = useRunStub.calls[0].args[0]
const { env } = useRunStub.calls[0].args[1]
assertEquals(env?.["TEA_PREFIX"], TEA_PREFIX.string)
Object.entries(expectedEnv).forEach(([key, value]) => {
assertEquals(env?.[key], value)
Expand All @@ -58,18 +59,17 @@ Deno.test("should enter repl - sh", { sanitizeResources: false, sanitizeOps: fal
})


Deno.test("repl errors", { sanitizeResources: false, sanitizeOps: false }, async test => {
Deno.test("repl errors", { sanitizeResources: false, sanitizeOps: false }, async test => {
await test.step("run error", async () => {
const {run, useRunInternals } = await createTestHarness()

const mockProc = newMockProcess()
mockProc.status = () => Promise.resolve({success: false, code: 123})
const mockProc = newMockProcess(() => Promise.resolve({success: false, code: 123, signal: null}))

const useRunStub = stub(useRunInternals, "nativeRun", returnsNext([mockProc]))

await assertRejects(async () => {
try {
await run(["sh"])
await run(["sh"])
} finally {
useRunStub.restore()
}
Expand All @@ -79,14 +79,13 @@ Deno.test("repl errors", { sanitizeResources: false, sanitizeOps: false }, async
await test.step("other error", async () => {
const {run, useRunInternals } = await createTestHarness()

const mockProc = newMockProcess()
mockProc.status = () => Promise.reject(new Error("test error"))
const mockProc = newMockProcess(() => Promise.reject(new Error("test error")))

const useRunStub = stub(useRunInternals, "nativeRun", returnsNext([mockProc]))

await assertRejects(async () => {
try {
await run(["sh"])
await run(["sh"])
} finally {
useRunStub.restore()
}
Expand Down
4 changes: 2 additions & 2 deletions tests/functional/script.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ Deno.test("run a python script", { sanitizeResources: false, sanitizeOps: false

const useRunSpy = spy(useRunInternals, "nativeRun")
try {
await run([scriptFile])
await run([scriptFile])
} finally {
useRunSpy.restore()
}

const [python, script] = useRunSpy.calls[0].args[0].cmd
const [python, script] = [useRunSpy.calls[0].args[0], ...useRunSpy.calls[0].args[1].args!]

assert(python.toString().startsWith("python3."))
assertEquals(script, scriptFile)
Expand Down
34 changes: 23 additions & 11 deletions tests/functional/testUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const createTestHarness = async (config?: TestConfig) => {
const [syncArgs, flags] = parseArgs(["--sync", "--silent"], teaDir.string)
init(flags)
updateConfig({ teaPrefix: new Path(TEA_PREFIX.string), env: { NO_COLOR: "1" } })
await run(syncArgs)
await run(syncArgs)
}

const runTea = async (args: string[], configOverrides: Partial<Config> = {}) => {
Expand All @@ -46,7 +46,7 @@ export const createTestHarness = async (config?: TestConfig) => {
init(flags)
updateConfig({ execPath: teaDir, teaPrefix: new Path(TEA_PREFIX.string), ...configOverrides })

await run(appArgs)
await run(appArgs)
} finally {
usePrintSpy.restore()
Deno.chdir(cwd)
Expand Down Expand Up @@ -75,15 +75,27 @@ function updateConfig(updated: Partial<Config>) {
useConfigInternals.setConfig({...config, ...updated, env: {...config.env, ...updated.env}})
}

// the Deno.Process object cannot be created externally with `new` so we'll just return a
// we need Deno.ChildProcress.status to be mutable
type Mutable<Type> = {
-readonly [Key in keyof Type]: Type[Key];
}

// the Deno.Process object cannot be created externally with `new` so we'll just return a
// ProcessLike object
export function newMockProcess(statusFunction?: () => Promise<Deno.ProcessStatus>): Deno.Process {
const status = statusFunction ?? (() => Promise.resolve({success: true, code: 0}))
export function newMockProcess(status?: () => Promise<Deno.CommandStatus>): Deno.Command {
return {
status,
output: () => Promise.resolve(""),
stderrOutput: () => Promise.resolve(""),
close: () => {
},
} as unknown as Deno.Process
output: function(): Promise<Deno.CommandOutput> { throw new Error("UNIMPLEMENTED") },
outputSync(): Deno.CommandOutput { throw new Error("UNIMPLEMENTED") },
spawn: () => ({
pid: 10,
stdin: new WritableStream<Uint8Array>(),
stdout: new ReadableStream<Uint8Array>(),
stderr: new ReadableStream<Uint8Array>(),
status: status ? status() : Promise.resolve({ success: true, code: 0, signal: null }),
output: () => Promise.resolve({ stdout: new Uint8Array(), stderr: new Uint8Array(), success: false, code: 1, signal: null }),
kill: _ => {},
ref: () => {},
unref: () => {}
})
}
}

0 comments on commit 12c9669

Please sign in to comment.