Skip to content

Commit 12c9669

Browse files
committed
Lint with deno 1.33
1 parent f3e2d03 commit 12c9669

7 files changed

Lines changed: 69 additions & 57 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
</p>
1717

1818

19-
# tea/cli 0.30.0
19+
# tea/cli 0.31.0
2020

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

src/hooks/useRun.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Path from "path"
22
import { isArray } from "is_what"
33

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

24-
const stdio = { stdout: 'inherit', stderr: 'inherit', stdin: 'inherit' } as Pick<Deno.RunOptions, 'stdout'|'stderr'|'stdin'>
24+
const stdio = { stdout: 'inherit', stderr: 'inherit', stdin: 'inherit' } as Pick<Deno.CommandOptions, 'stdout'|'stderr'|'stdin'>
2525
if (spin) {
2626
stdio.stderr = stdio.stdout = 'piped'
2727
}
2828

29-
let proc: Deno.Process | undefined
29+
let proc: Deno.ChildProcess | undefined
3030
try {
31-
proc = _internals.nativeRun({ ...opts, cmd, cwd, ...stdio })
32-
const exit = await proc.status()
31+
proc = _internals.nativeRun(cmd.shift()!, { ...opts, args: cmd, cwd, ...stdio }).spawn()
32+
const exit = await proc.status
3333
console.verbose({ exit })
3434
if (!exit.success) throw new RunError(exit.code, cmd)
3535
} catch (err) {
3636
if (spin && proc) {
3737
//FIXME this doesn’t result in the output being correctly interlaced
3838
// ie. stderr and stdout may (probably) have been output interleaved rather than sequentially
3939
const decode = (() => { const e = new TextDecoder(); return e.decode.bind(e) })()
40-
console.error(decode(await proc.output()))
41-
console.error(decode(await proc.stderrOutput()))
40+
console.error(decode((await proc.output()).stdout))
41+
console.error(decode((await proc.output()).stderr))
4242
}
43+
4344
err.cmd = cmd // help us out since deno-devs don’t want to
4445
throw err
45-
} finally {
46-
proc?.close()
4746
}
4847
}
4948

50-
const nativeRun = (runOptions: Deno.RunOptions) => Deno.run(runOptions)
49+
50+
const nativeRun = (cmd: string, opts: Deno.CommandOptions) => new Deno.Command(cmd, opts)
5151

5252
// _internals are used for testing
5353
export const _internals = {

src/vendor/Path.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -317,12 +317,12 @@ export default class Path {
317317

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

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

327327
return to
328328
}

tests/functional/exec.test.ts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,54 +8,55 @@ Deno.test("exec", { sanitizeResources: false, sanitizeOps: false }, async () =>
88

99
const useRunSpy = spy(useRunInternals, "nativeRun")
1010
try {
11-
await run(["node", "--version"])
11+
await run(["node", "--version"])
1212
} finally {
1313
useRunSpy.restore()
1414
}
1515

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

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

2223
const useRunSpy = spy(useRunInternals, "nativeRun")
2324
try {
24-
await run(["sh", "-c", "echo $TEA_PREFIX"])
25+
await run(["sh", "-c", "echo $TEA_PREFIX"])
2526
} finally {
2627
useRunSpy.restore()
2728
}
2829

29-
assertEquals(useRunSpy.calls[0].args[0].env?.["TEA_PREFIX"], TEA_PREFIX.string)
30+
assertEquals(useRunSpy.calls[0].args[1].env?.["TEA_PREFIX"], TEA_PREFIX.string)
3031
})
3132

3233
Deno.test("exec run errors", { sanitizeResources: false, sanitizeOps: false }, async test => {
3334
const tests = [
3435
{
3536
name: "exit error",
36-
procStatus: (): Promise<Deno.ProcessStatus> => Promise.resolve({success: false, code: 123}),
37+
procStatus: (): Promise<Deno.CommandStatus> => Promise.resolve({success: false, code: 123, signal: null}),
3738
expectedErr: "exiting with code: 123",
38-
},
39+
},
3940
{
4041
name: "normal error",
41-
procStatus: (): Promise<Deno.ProcessStatus> => Promise.reject(new Error("test error")),
42+
procStatus: (): Promise<Deno.CommandStatus> => Promise.reject(new Error("test error")),
4243
expectedErr: "exiting with code: 1",
43-
},
44+
},
4445
{
4546
name: "tea error",
46-
procStatus: (): Promise<Deno.ProcessStatus> => Promise.reject(new TeaError("confused: interpreter", {})),
47+
procStatus: (): Promise<Deno.CommandStatus> => Promise.reject(new TeaError("confused: interpreter", {})),
4748
expectedErr: "exiting with code: 1",
48-
},
49+
},
4950
{
5051
name: "not found",
51-
procStatus: (): Promise<Deno.ProcessStatus> => Promise.reject(new Deno.errors.NotFound()),
52+
procStatus: (): Promise<Deno.CommandStatus> => Promise.reject(new Deno.errors.NotFound()),
5253
expectedErr: "exiting with code: 127",
53-
},
54+
},
5455
{
5556
name: "permission denied",
56-
procStatus: (): Promise<Deno.ProcessStatus> => Promise.reject(new Deno.errors.PermissionDenied()),
57+
procStatus: (): Promise<Deno.CommandStatus> => Promise.reject(new Deno.errors.PermissionDenied()),
5758
expectedErr: "exiting with code: 127",
58-
},
59+
},
5960
]
6061

6162
for (const { name, procStatus, expectedErr } of tests) {
@@ -66,7 +67,7 @@ Deno.test("exec run errors", { sanitizeResources: false, sanitizeOps: false }, a
6667
const useRunStub = stub(useRunInternals, "nativeRun", returnsNext([mockProc]))
6768
await assertRejects(async () => {
6869
try {
69-
await run(["node", "--version"])
70+
await run(["node", "--version"])
7071
} finally {
7172
useRunStub.restore()
7273
}
@@ -76,7 +77,7 @@ Deno.test("exec run errors", { sanitizeResources: false, sanitizeOps: false }, a
7677
})
7778

7879
Deno.test("exec forkbomb protector", { sanitizeResources: false, sanitizeOps: false }, async () => {
79-
const {run } = await createTestHarness()
80+
const { run } = await createTestHarness()
8081
await assertRejects(
8182
() => run(["sh", "-c", "echo $TEA_PREFIX"], { env: {TEA_FORK_BOMB_PROTECTOR: "21" }}),
8283
"FORK BOMB KILL SWITCH ACTIVATED")

tests/functional/repl.test.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import { stub, returnsNext } from "deno/testing/mock.ts"
33
import { ExitError } from "types"
44
import { createTestHarness, newMockProcess } from "./testUtils.ts"
55

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

4343
try {
44-
await run(["sh"], { env: { SHELL: shell } })
44+
await run(["sh"], { env: { SHELL: shell } })
4545
} finally {
4646
useRunStub.restore()
4747
}
4848

49-
assertEquals(useRunStub.calls[0].args[0].cmd, expectedCmd)
49+
const foo = [useRunStub.calls[0].args[0], ...useRunStub.calls[0].args[1].args!]
50+
assertEquals(foo, expectedCmd)
5051

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

6061

61-
Deno.test("repl errors", { sanitizeResources: false, sanitizeOps: false }, async test => {
62+
Deno.test("repl errors", { sanitizeResources: false, sanitizeOps: false }, async test => {
6263
await test.step("run error", async () => {
6364
const {run, useRunInternals } = await createTestHarness()
6465

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

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

7070
await assertRejects(async () => {
7171
try {
72-
await run(["sh"])
72+
await run(["sh"])
7373
} finally {
7474
useRunStub.restore()
7575
}
@@ -79,14 +79,13 @@ Deno.test("repl errors", { sanitizeResources: false, sanitizeOps: false }, async
7979
await test.step("other error", async () => {
8080
const {run, useRunInternals } = await createTestHarness()
8181

82-
const mockProc = newMockProcess()
83-
mockProc.status = () => Promise.reject(new Error("test error"))
82+
const mockProc = newMockProcess(() => Promise.reject(new Error("test error")))
8483

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

8786
await assertRejects(async () => {
8887
try {
89-
await run(["sh"])
88+
await run(["sh"])
9089
} finally {
9190
useRunStub.restore()
9291
}

tests/functional/script.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ Deno.test("run a python script", { sanitizeResources: false, sanitizeOps: false
1111

1212
const useRunSpy = spy(useRunInternals, "nativeRun")
1313
try {
14-
await run([scriptFile])
14+
await run([scriptFile])
1515
} finally {
1616
useRunSpy.restore()
1717
}
1818

19-
const [python, script] = useRunSpy.calls[0].args[0].cmd
19+
const [python, script] = [useRunSpy.calls[0].args[0], ...useRunSpy.calls[0].args[1].args!]
2020

2121
assert(python.toString().startsWith("python3."))
2222
assertEquals(script, scriptFile)

tests/functional/testUtils.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export const createTestHarness = async (config?: TestConfig) => {
2828
const [syncArgs, flags] = parseArgs(["--sync", "--silent"], teaDir.string)
2929
init(flags)
3030
updateConfig({ teaPrefix: new Path(TEA_PREFIX.string), env: { NO_COLOR: "1" } })
31-
await run(syncArgs)
31+
await run(syncArgs)
3232
}
3333

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

49-
await run(appArgs)
49+
await run(appArgs)
5050
} finally {
5151
usePrintSpy.restore()
5252
Deno.chdir(cwd)
@@ -75,15 +75,27 @@ function updateConfig(updated: Partial<Config>) {
7575
useConfigInternals.setConfig({...config, ...updated, env: {...config.env, ...updated.env}})
7676
}
7777

78-
// the Deno.Process object cannot be created externally with `new` so we'll just return a
78+
// we need Deno.ChildProcress.status to be mutable
79+
type Mutable<Type> = {
80+
-readonly [Key in keyof Type]: Type[Key];
81+
}
82+
83+
// the Deno.Process object cannot be created externally with `new` so we'll just return a
7984
// ProcessLike object
80-
export function newMockProcess(statusFunction?: () => Promise<Deno.ProcessStatus>): Deno.Process {
81-
const status = statusFunction ?? (() => Promise.resolve({success: true, code: 0}))
85+
export function newMockProcess(status?: () => Promise<Deno.CommandStatus>): Deno.Command {
8286
return {
83-
status,
84-
output: () => Promise.resolve(""),
85-
stderrOutput: () => Promise.resolve(""),
86-
close: () => {
87-
},
88-
} as unknown as Deno.Process
87+
output: function(): Promise<Deno.CommandOutput> { throw new Error("UNIMPLEMENTED") },
88+
outputSync(): Deno.CommandOutput { throw new Error("UNIMPLEMENTED") },
89+
spawn: () => ({
90+
pid: 10,
91+
stdin: new WritableStream<Uint8Array>(),
92+
stdout: new ReadableStream<Uint8Array>(),
93+
stderr: new ReadableStream<Uint8Array>(),
94+
status: status ? status() : Promise.resolve({ success: true, code: 0, signal: null }),
95+
output: () => Promise.resolve({ stdout: new Uint8Array(), stderr: new Uint8Array(), success: false, code: 1, signal: null }),
96+
kill: _ => {},
97+
ref: () => {},
98+
unref: () => {}
99+
})
100+
}
89101
}

0 commit comments

Comments
 (0)