@vzn/vx 0.0.580 → 0.0.581
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/graph/task-graph.ts +39 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.581",
|
|
4
4
|
"description": "The fastest task runner and build cache for JavaScript monorepos.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
"node": ">=18"
|
|
22
22
|
},
|
|
23
23
|
"optionalDependencies": {
|
|
24
|
-
"@vzn/vx-linux-x64": "0.0.
|
|
25
|
-
"@vzn/vx-linux-arm64": "0.0.
|
|
26
|
-
"@vzn/vx-darwin-x64": "0.0.
|
|
27
|
-
"@vzn/vx-darwin-arm64": "0.0.
|
|
24
|
+
"@vzn/vx-linux-x64": "0.0.581",
|
|
25
|
+
"@vzn/vx-linux-arm64": "0.0.581",
|
|
26
|
+
"@vzn/vx-darwin-x64": "0.0.581",
|
|
27
|
+
"@vzn/vx-darwin-arm64": "0.0.581"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@anthropic-ai/sandbox-runtime": "^0.0.76"
|
package/src/graph/task-graph.ts
CHANGED
|
@@ -553,6 +553,7 @@ export function checkGraph(
|
|
|
553
553
|
delete node.addsToOutputsOf
|
|
554
554
|
delete node.outputsAddedToBy
|
|
555
555
|
}
|
|
556
|
+
for (const node of nodes.values()) refuseSelfClean(node)
|
|
556
557
|
detectCycle(nodes)
|
|
557
558
|
detectOutputCollisions(nodes, workspaceRoot, rules?.exclusiveOutputs !== false)
|
|
558
559
|
if (rules?.upfrontKeys !== false) detectInputOverlaps(nodes, workspaceRoot)
|
|
@@ -1123,6 +1124,44 @@ export function outputTakenBack(output: string, negatives: readonly string[]): b
|
|
|
1123
1124
|
)
|
|
1124
1125
|
}
|
|
1125
1126
|
|
|
1127
|
+
/**
|
|
1128
|
+
* A task whose input entry its own outputs take back whole cleans its own
|
|
1129
|
+
* sources: vx removes a task's outputs before it runs, so a formatter
|
|
1130
|
+
* declaring `src/**` as both deleted every committed file under `src`,
|
|
1131
|
+
* and its key read nothing (hunt 8). Always refused, whatever the rules.
|
|
1132
|
+
*/
|
|
1133
|
+
function refuseSelfClean(node: TaskNode): void {
|
|
1134
|
+
const cache = node.config.cache
|
|
1135
|
+
if (cache === undefined) return
|
|
1136
|
+
for (const field of ['files', 'workspaceFiles'] as const) {
|
|
1137
|
+
const inputs = splitNegations(cache.inputs[field] ?? [])
|
|
1138
|
+
const out = splitNegations(cache.outputs[field] ?? [])
|
|
1139
|
+
const outputs = out.positive
|
|
1140
|
+
if (outputs.length === 0) continue
|
|
1141
|
+
const roots = outputs.map((g) => rootless(staticPrefix(g)))
|
|
1142
|
+
for (const gi of inputs.positive) {
|
|
1143
|
+
// Only an output rooted at or above the input's prefix can cover it;
|
|
1144
|
+
// the prefix test keeps the glob matchers off the common disjoint pair.
|
|
1145
|
+
const pi = rootless(staticPrefix(gi))
|
|
1146
|
+
const near = outputs.filter((_, k) => {
|
|
1147
|
+
const r = roots[k]!
|
|
1148
|
+
return r === '' || pi === r || pi.startsWith(`${r}/`)
|
|
1149
|
+
})
|
|
1150
|
+
// Taken back by the task's own `!` inputs, or by an output `!` (no
|
|
1151
|
+
// output, so never cleaned: A-44), the entry reads what it says.
|
|
1152
|
+
if (near.length === 0 || outputTakenBack(gi, inputs.negative)) continue
|
|
1153
|
+
if (outputTakenBack(gi, out.negative)) continue
|
|
1154
|
+
if (!outputTakenBack(gi, near)) continue
|
|
1155
|
+
throw new UserError(
|
|
1156
|
+
`${node.id}: every file ${JSON.stringify(gi)} in cache.inputs.${field} selects is also ` +
|
|
1157
|
+
`its own output — vx removes a task's outputs before it runs, so the task would ` +
|
|
1158
|
+
`delete its own sources. A task that rewrites files in place (a formatter) declares ` +
|
|
1159
|
+
`no outputs.`,
|
|
1160
|
+
)
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1126
1165
|
/** One task's inputs (`reads`) or outputs in one namespace, for `detectInputOverlaps`. */
|
|
1127
1166
|
interface Side {
|
|
1128
1167
|
node: TaskNode
|