Skip to content

Commit d79a638

Browse files
authored
feat: let cwdHook be configurable (#765)
* feat: let `cwdHook` be configurable * test: add `$.cwdHook` test * feat: disable $.cwdHook by default BREAKING CHANGE: affects legacy cd() flow * test: fix pkg.test.js cd() * chore: rename `setupSmth` helpers to `useSmth`
1 parent b75c71a commit d79a638

File tree

7 files changed

+35
-18
lines changed

7 files changed

+35
-18
lines changed

src/core.ts

+12-10
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import assert from 'node:assert'
1616
import { spawn, spawnSync, StdioNull, StdioPipe } from 'node:child_process'
17-
import { AsyncLocalStorage, createHook } from 'node:async_hooks'
17+
import { AsyncHook, AsyncLocalStorage, createHook } from 'node:async_hooks'
1818
import { Readable, Writable } from 'node:stream'
1919
import { inspect } from 'node:util'
2020
import {
@@ -38,6 +38,7 @@ import {
3838
parseDuration,
3939
quote,
4040
quotePowerShell,
41+
noquote,
4142
} from './util.js'
4243

4344
export interface Shell {
@@ -74,14 +75,18 @@ export interface Options {
7475
}
7576

7677
const storage = new AsyncLocalStorage<Options>()
77-
const hook = createHook({
78+
const cwdSyncHook: AsyncHook & { enabled?: boolean } = createHook({
7879
init: syncCwd,
7980
before: syncCwd,
8081
promiseResolve: syncCwd,
8182
after: syncCwd,
8283
destroy: syncCwd,
8384
})
84-
hook.enable()
85+
86+
export function syncProcessCwd(flag: boolean = true) {
87+
if (flag) cwdSyncHook.enable()
88+
else cwdSyncHook.disable()
89+
}
8590

8691
export const defaults: Options = {
8792
[processCwd]: process.cwd(),
@@ -94,24 +99,22 @@ export const defaults: Options = {
9499
quiet: false,
95100
prefix: '',
96101
postfix: '',
97-
quote: () => {
98-
throw new Error('No quote function is defined: https://ï.at/no-quote-func')
99-
},
102+
quote: noquote,
100103
spawn,
101104
spawnSync,
102105
log,
103106
kill,
104107
}
105108
const isWin = process.platform == 'win32'
106109

107-
export function setupPowerShell() {
110+
export function usePowerShell() {
108111
$.shell = which.sync('powershell.exe')
109112
$.prefix = ''
110113
$.postfix = '; exit $LastExitCode'
111114
$.quote = quotePowerShell
112115
}
113116

114-
export function setupBash() {
117+
export function useBash() {
115118
$.shell = which.sync('bash')
116119
$.prefix = 'set -euo pipefail;'
117120
$.quote = quote
@@ -184,9 +187,8 @@ export const $: Shell & Options = new Proxy<Shell & Options>(
184187
},
185188
}
186189
)
187-
188190
try {
189-
setupBash()
191+
useBash()
190192
} catch (err) {}
191193

192194
type Resolve = (out: ProcessOutput) => void

src/globals.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ declare global {
4141
var quote: typeof _.quote
4242
var quotePowerShell: typeof _.quotePowerShell
4343
var retry: typeof _.retry
44-
var setupPowerShell: typeof _.setupPowerShell
44+
var usePowerShell: typeof _.usePowerShell
45+
var useBash: typeof _.useBash
4546
var sleep: typeof _.sleep
4647
var spinner: typeof _.spinner
4748
var stdin: typeof _.stdin

src/util.ts

+4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ export function normalizeMultilinePieces(
4242
)
4343
}
4444

45+
export function noquote(): string {
46+
throw new Error('No quote function is defined: https://ï.at/no-quote-func')
47+
}
48+
4549
export function quote(arg: string) {
4650
if (/^[a-z0-9/_.\-@:=]+$/i.test(arg) || arg === '') {
4751
return arg

test/core.test.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -263,25 +263,26 @@ describe('core', () => {
263263
}
264264
})
265265

266-
test('cd() does affect parallel contexts', async () => {
266+
test('cd() does not affect parallel contexts ($.cwdSyncHook enabled)', async () => {
267+
syncProcessCwd()
267268
const cwd = process.cwd()
268269
try {
269270
fs.mkdirpSync('/tmp/zx-cd-parallel/one/two')
270271
await Promise.all([
271272
within(async () => {
272273
assert.equal(process.cwd(), cwd)
273-
await sleep(1)
274274
cd('/tmp/zx-cd-parallel/one')
275+
await sleep(Math.random() * 15)
275276
assert.ok(process.cwd().endsWith('/tmp/zx-cd-parallel/one'))
276277
}),
277278
within(async () => {
278279
assert.equal(process.cwd(), cwd)
279-
await sleep(2)
280+
await sleep(Math.random() * 15)
280281
assert.equal(process.cwd(), cwd)
281282
}),
282283
within(async () => {
283284
assert.equal(process.cwd(), cwd)
284-
await sleep(3)
285+
await sleep(Math.random() * 15)
285286
$.cwd = '/tmp/zx-cd-parallel/one/two'
286287
assert.equal(process.cwd(), cwd)
287288
assert.ok(
@@ -297,6 +298,7 @@ describe('core', () => {
297298
} finally {
298299
fs.rmSync('/tmp/zx-cd-parallel', { recursive: true })
299300
cd(cwd)
301+
syncProcessCwd(false)
300302
}
301303
})
302304

test/index.test.js

+6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ import {
2020
$,
2121
log,
2222
cd,
23+
syncProcessCwd,
24+
usePowerShell,
25+
useBash,
2326
kill,
2427
ProcessOutput,
2528
ProcessPromise,
@@ -60,10 +63,13 @@ describe('index', () => {
6063
assert(ProcessOutput)
6164
assert(ProcessPromise)
6265
assert(cd)
66+
assert(syncProcessCwd)
6367
assert(log)
6468
assert(kill)
6569
assert(defaults)
6670
assert(within)
71+
assert(usePowerShell)
72+
assert(useBash)
6773

6874
// goods
6975
assert(argv)

test/package.test.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
// limitations under the License.
1414

1515
import assert from 'node:assert'
16-
import { test, describe, beforeEach } from 'node:test'
16+
import { test, describe, beforeEach, before, after } from 'node:test'
1717
import '../build/globals.js'
1818

1919
describe('package', () => {
20+
before(() => syncProcessCwd())
21+
after(() => syncProcessCwd(false))
2022
beforeEach(async () => {
2123
const pack = await $`npm pack`
2224
await $`tar xf ${pack}`

test/smoke/win32.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ _describe('win32', () => {
2424
assert.match(p.stdout, /bash/)
2525

2626
await within(async () => {
27-
setupPowerShell()
27+
usePowerShell()
2828
assert.match($.shell, /powershell/i)
2929
const p = await $`get-host`
3030
assert.match(p.stdout, /PowerShell/)
@@ -33,7 +33,7 @@ _describe('win32', () => {
3333

3434
test('quotePowerShell works', async () => {
3535
await within(async () => {
36-
setupPowerShell()
36+
usePowerShell()
3737
const p = await $`echo ${`Windows 'rulez!'`}`
3838
assert.match(p.stdout, /Windows 'rulez!'/)
3939
})

0 commit comments

Comments
 (0)