@vzn/vx 0.0.73 → 0.0.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/src/cache/inputs.ts +26 -0
- package/src/cli/run.ts +5 -3
- package/src/exec/kill-tree.ts +15 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.75",
|
|
4
4
|
"description": "An open, extensible monorepo task runner.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"node": ">=18"
|
|
18
18
|
},
|
|
19
19
|
"optionalDependencies": {
|
|
20
|
-
"@vzn/vx-linux-x64": "0.0.
|
|
21
|
-
"@vzn/vx-linux-arm64": "0.0.
|
|
22
|
-
"@vzn/vx-darwin-x64": "0.0.
|
|
23
|
-
"@vzn/vx-darwin-arm64": "0.0.
|
|
20
|
+
"@vzn/vx-linux-x64": "0.0.75",
|
|
21
|
+
"@vzn/vx-linux-arm64": "0.0.75",
|
|
22
|
+
"@vzn/vx-darwin-x64": "0.0.75",
|
|
23
|
+
"@vzn/vx-darwin-arm64": "0.0.75"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@anthropic-ai/sandbox-runtime": "^0.0.76"
|
package/src/cache/inputs.ts
CHANGED
|
@@ -234,6 +234,7 @@ async function resolveWorkspaceFiles(args: {
|
|
|
234
234
|
}): Promise<string[]> {
|
|
235
235
|
const positive: string[] = []
|
|
236
236
|
const negative: string[] = []
|
|
237
|
+
refuseOneAlternativeBrace(args.workspaceFiles, 'workspaceFiles')
|
|
237
238
|
for (const entry of args.workspaceFiles) {
|
|
238
239
|
if (entry.startsWith('!')) negative.push(entry.slice(1))
|
|
239
240
|
else positive.push(entry)
|
|
@@ -895,6 +896,30 @@ function refuseUndecodable(
|
|
|
895
896
|
)
|
|
896
897
|
}
|
|
897
898
|
|
|
899
|
+
const ONE_ALTERNATIVE_BRACE = /(?<!\\)\{[^{},]*\}/
|
|
900
|
+
|
|
901
|
+
/**
|
|
902
|
+
* `Bun.Glob` reads `{b}` as a brace of one alternative, so `src/{b}.ts`
|
|
903
|
+
* matches `src/b.ts` and never a file named `{b}.ts`: that file stays out
|
|
904
|
+
* of the key and an edit to it is a hit. Neither reading is sure to be
|
|
905
|
+
* the one meant, so the entry is refused with both spellings.
|
|
906
|
+
*/
|
|
907
|
+
function refuseOneAlternativeBrace(
|
|
908
|
+
entries: readonly string[],
|
|
909
|
+
field: 'files' | 'workspaceFiles',
|
|
910
|
+
): void {
|
|
911
|
+
for (const entry of entries) {
|
|
912
|
+
const m = ONE_ALTERNATIVE_BRACE.exec(entry)
|
|
913
|
+
if (m === null) continue
|
|
914
|
+
const inner = m[0].slice(1, -1)
|
|
915
|
+
throw new UserError(
|
|
916
|
+
`cache.inputs.${field}: "${entry}" holds a brace with one alternative, which matches ` +
|
|
917
|
+
`"${inner}" and never a name holding "${m[0]}". Write "${entry.replace(m[0], inner)}", ` +
|
|
918
|
+
`or "${entry.replace(m[0], `\\{${inner}\\}`)}" for the braces themselves.`,
|
|
919
|
+
)
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
|
|
898
923
|
async function resolveFiles(args: ResolveFilesArgs): Promise<string[]> {
|
|
899
924
|
const positive: string[] = []
|
|
900
925
|
const negative: string[] = []
|
|
@@ -902,6 +927,7 @@ async function resolveFiles(args: ResolveFilesArgs): Promise<string[]> {
|
|
|
902
927
|
if (args.files === undefined) {
|
|
903
928
|
positive.push(...DEFAULT_FILE_GLOBS)
|
|
904
929
|
} else {
|
|
930
|
+
refuseOneAlternativeBrace(args.files, 'files')
|
|
905
931
|
for (const entry of args.files) {
|
|
906
932
|
if (entry.startsWith('!')) negative.push(entry.slice(1))
|
|
907
933
|
else positive.push(entry)
|
package/src/cli/run.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { appendFileSync, mkdirSync } from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { documentedFlags, seeHelp } from './help.js'
|
|
4
4
|
import { defaultAffectedBase, findWorkspaceRoot } from '../workspace/index.js'
|
|
@@ -649,8 +649,10 @@ export async function runCmd(args: readonly string[]): Promise<number> {
|
|
|
649
649
|
// behaviour change rather than a drop-in.
|
|
650
650
|
// Its directory made first, as `--summarize`, `--profile` and
|
|
651
651
|
// `--graph` make theirs: `nr/r.md` failed alone of the four (item 993).
|
|
652
|
-
|
|
653
|
-
|
|
652
|
+
// Sync: on a Ctrl-C the signal path exits once stdout drains, and
|
|
653
|
+
// an awaited write lost the race every time (E-23).
|
|
654
|
+
mkdirSync(path.dirname(target), { recursive: true })
|
|
655
|
+
appendFileSync(target, md)
|
|
654
656
|
} catch (err) {
|
|
655
657
|
// Same contract as --summarize / --profile: the run already
|
|
656
658
|
// happened, so a write failure is reported, not fatal.
|
package/src/exec/kill-tree.ts
CHANGED
|
@@ -87,7 +87,21 @@ function startGuard(): void {
|
|
|
87
87
|
detached: true,
|
|
88
88
|
})
|
|
89
89
|
guard.unref()
|
|
90
|
-
|
|
90
|
+
const fd = guard.stdio[3] as number
|
|
91
|
+
guardFd = fd
|
|
92
|
+
// A guard that has died (killed, the OOM killer) is handed to no later
|
|
93
|
+
// spawn: its pipe is broken, and a shell whose printf buffers (bash as
|
|
94
|
+
// macOS's sh) flushed the failed `+<pgid>` line into the task's own
|
|
95
|
+
// stdout, cached replay included (B-10).
|
|
96
|
+
void guard.exited.then(() => {
|
|
97
|
+
if (guardFd !== fd) return
|
|
98
|
+
guardFd = null
|
|
99
|
+
try {
|
|
100
|
+
closeSync(fd)
|
|
101
|
+
} catch {
|
|
102
|
+
// already closed
|
|
103
|
+
}
|
|
104
|
+
})
|
|
91
105
|
} catch {
|
|
92
106
|
// The limit as it was: nothing takes the groups down.
|
|
93
107
|
}
|