@vzn/vx 0.0.62 → 0.0.64
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 +5 -1
- package/src/graph/scheduler.ts +10 -4
- package/src/util/index.ts +1 -0
- package/src/util/paths.ts +34 -0
- package/src/workspace/workspace.ts +7 -35
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.64",
|
|
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.64",
|
|
21
|
+
"@vzn/vx-linux-arm64": "0.0.64",
|
|
22
|
+
"@vzn/vx-darwin-x64": "0.0.64",
|
|
23
|
+
"@vzn/vx-darwin-arm64": "0.0.64"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@anthropic-ai/sandbox-runtime": "^0.0.76"
|
package/src/cache/inputs.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
isExecutableMissing,
|
|
26
26
|
isLiteralPattern,
|
|
27
27
|
normalizeGlob,
|
|
28
|
+
slashBraceExpansions,
|
|
28
29
|
taskGlob,
|
|
29
30
|
UserError,
|
|
30
31
|
} from '../util/index.js'
|
|
@@ -1062,7 +1063,10 @@ async function scanUnion(
|
|
|
1062
1063
|
cwd: string,
|
|
1063
1064
|
): Promise<Set<string>> {
|
|
1064
1065
|
const matches = new Set<string>()
|
|
1065
|
-
for
|
|
1066
|
+
// `Bun.Glob`'s scan finds nothing for a brace whose alternatives hold a
|
|
1067
|
+
// `/`: `{dist,lib/esm}/**` saved an empty artifact, and a hit restored
|
|
1068
|
+
// nothing over a cleaned tree (A-10). Expanded here, as discovery does.
|
|
1069
|
+
for (const pattern of positive.flatMap(slashBraceExpansions)) {
|
|
1066
1070
|
const glob = globFor(pattern)
|
|
1067
1071
|
for (const rel of glob.scanSync({ cwd, onlyFiles: false, followSymlinks: false, dot: true })) {
|
|
1068
1072
|
if (excludeGlobs.some((g) => g.match(rel))) continue
|
package/src/graph/scheduler.ts
CHANGED
|
@@ -399,6 +399,9 @@ export async function runGraph(options: ScheduleOptions): Promise<Map<string, Ta
|
|
|
399
399
|
const restoreRoom = (): boolean =>
|
|
400
400
|
serial ? active + activeRestore < 1 : activeRestore < restoreConcurrency
|
|
401
401
|
let resolved = false
|
|
402
|
+
// A refusal's text → the first task that said it. A corrupt cache index
|
|
403
|
+
// reaches every lookup as one UserError; a repeat names the first.
|
|
404
|
+
const refusedBy = new Map<string, string>()
|
|
402
405
|
|
|
403
406
|
// Admission policy over the count limit (a plugin's `admit`). Inactive
|
|
404
407
|
// → the tick loop short-circuits before any of this and behaves
|
|
@@ -717,10 +720,13 @@ export async function runGraph(options: ScheduleOptions): Promise<Map<string, Ta
|
|
|
717
720
|
// UserError is a config/input failure (e.g. a failed
|
|
718
721
|
// `cache.inputs.runtime` command), not a vx bug — report it
|
|
719
722
|
// plainly, never as an "internal error".
|
|
720
|
-
if (isUserError(err)) {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
723
|
+
if (isUserError(err) || isFsRefusal(err)) {
|
|
724
|
+
const text = isUserError(err) ? message : `${message} — ${fsRefusalHint(err)}`
|
|
725
|
+
const first = refusedBy.get(text)
|
|
726
|
+
if (first === undefined) refusedBy.set(text, id)
|
|
727
|
+
process.stderr.write(
|
|
728
|
+
`[vx] ${id}: ${first === undefined ? text : `as ${first} above`}\n`,
|
|
729
|
+
)
|
|
724
730
|
} else {
|
|
725
731
|
const named = err instanceof Error && err.name !== 'Error' ? `${err.name}: ` : ''
|
|
726
732
|
// A wrapped error's cause is the fact the reader needs (a
|
package/src/util/index.ts
CHANGED
package/src/util/paths.ts
CHANGED
|
@@ -227,3 +227,37 @@ export function asTrees(patterns: readonly string[]): string[] {
|
|
|
227
227
|
}
|
|
228
228
|
return out
|
|
229
229
|
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* `pattern` with its first brace group expanded, recursively, while that
|
|
233
|
+
* group holds a `/`; any other pattern as itself, since `Bun.Glob`
|
|
234
|
+
* expands a slash-free brace on its own. An unbalanced or escaped brace
|
|
235
|
+
* is left to the glob.
|
|
236
|
+
*/
|
|
237
|
+
export function slashBraceExpansions(pattern: string): string[] {
|
|
238
|
+
if (pattern.includes('\\')) return [pattern]
|
|
239
|
+
for (let open = pattern.indexOf('{'); open !== -1; open = pattern.indexOf('{', open + 1)) {
|
|
240
|
+
let depth = 0
|
|
241
|
+
const cuts: number[] = []
|
|
242
|
+
let close = -1
|
|
243
|
+
for (let i = open; i < pattern.length && close === -1; i++) {
|
|
244
|
+
const c = pattern[i]
|
|
245
|
+
if (c === '{') depth++
|
|
246
|
+
else if (c === '}' && --depth === 0) close = i
|
|
247
|
+
else if (c === ',' && depth === 1) cuts.push(i)
|
|
248
|
+
}
|
|
249
|
+
if (close === -1) return [pattern]
|
|
250
|
+
const body = pattern.slice(open + 1, close)
|
|
251
|
+
if (cuts.length === 0 || !body.includes('/')) continue
|
|
252
|
+
const head = pattern.slice(0, open)
|
|
253
|
+
const tail = pattern.slice(close + 1)
|
|
254
|
+
const bounds = [open, ...cuts, close]
|
|
255
|
+
const out: string[] = []
|
|
256
|
+
for (let k = 0; k + 1 < bounds.length; k++) {
|
|
257
|
+
const alt = pattern.slice(bounds[k]! + 1, bounds[k + 1])
|
|
258
|
+
out.push(...slashBraceExpansions(head + alt + tail))
|
|
259
|
+
}
|
|
260
|
+
return [...new Set(out)]
|
|
261
|
+
}
|
|
262
|
+
return [pattern]
|
|
263
|
+
}
|
|
@@ -2,7 +2,13 @@ import type { Dirent } from 'node:fs'
|
|
|
2
2
|
import { readdir, stat } from 'node:fs/promises'
|
|
3
3
|
import path from 'node:path'
|
|
4
4
|
import type { ProjectConfig, WorkspaceConfig } from '../config.js'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
BUN_GLOB_WILDCARDS,
|
|
7
|
+
relPosix,
|
|
8
|
+
slashBraceExpansions,
|
|
9
|
+
UserError,
|
|
10
|
+
normalizeBunGlob,
|
|
11
|
+
} from '../util/index.js'
|
|
6
12
|
import { type LoadReads, readOnce } from './load-reads.js'
|
|
7
13
|
|
|
8
14
|
export interface PackageJson {
|
|
@@ -441,40 +447,6 @@ async function memberDirs(root: string, pattern: string): Promise<string[]> {
|
|
|
441
447
|
return dirs
|
|
442
448
|
}
|
|
443
449
|
|
|
444
|
-
/**
|
|
445
|
-
* `pattern` with its first brace group expanded, recursively, while that
|
|
446
|
-
* group holds a `/`; any other pattern as itself, since `Bun.Glob`
|
|
447
|
-
* expands a slash-free brace on its own. An unbalanced or escaped brace
|
|
448
|
-
* is left to the glob.
|
|
449
|
-
*/
|
|
450
|
-
function slashBraceExpansions(pattern: string): string[] {
|
|
451
|
-
if (pattern.includes('\\')) return [pattern]
|
|
452
|
-
for (let open = pattern.indexOf('{'); open !== -1; open = pattern.indexOf('{', open + 1)) {
|
|
453
|
-
let depth = 0
|
|
454
|
-
const cuts: number[] = []
|
|
455
|
-
let close = -1
|
|
456
|
-
for (let i = open; i < pattern.length && close === -1; i++) {
|
|
457
|
-
const c = pattern[i]
|
|
458
|
-
if (c === '{') depth++
|
|
459
|
-
else if (c === '}' && --depth === 0) close = i
|
|
460
|
-
else if (c === ',' && depth === 1) cuts.push(i)
|
|
461
|
-
}
|
|
462
|
-
if (close === -1) return [pattern]
|
|
463
|
-
const body = pattern.slice(open + 1, close)
|
|
464
|
-
if (cuts.length === 0 || !body.includes('/')) continue
|
|
465
|
-
const head = pattern.slice(0, open)
|
|
466
|
-
const tail = pattern.slice(close + 1)
|
|
467
|
-
const bounds = [open, ...cuts, close]
|
|
468
|
-
const out: string[] = []
|
|
469
|
-
for (let k = 0; k + 1 < bounds.length; k++) {
|
|
470
|
-
const alt = pattern.slice(bounds[k]! + 1, bounds[k + 1])
|
|
471
|
-
out.push(...slashBraceExpansions(head + alt + tail))
|
|
472
|
-
}
|
|
473
|
-
return [...new Set(out)]
|
|
474
|
-
}
|
|
475
|
-
return [pattern]
|
|
476
|
-
}
|
|
477
|
-
|
|
478
450
|
/**
|
|
479
451
|
* The project's config file, by `PROJECT_CONFIG_FILENAMES` precedence, or null.
|
|
480
452
|
*
|