@stll/oxlint-config 2.0.0 → 2.1.1
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/README.md +18 -1
- package/dist/consumer-node-support.cjs +2 -2
- package/dist/consumer-node-support.mjs +1 -1
- package/dist/dependabot.d.cts +8 -0
- package/dist/dependabot.d.mts +8 -0
- package/dist/git-tracked-output.cjs +1 -1
- package/dist/git-tracked-output.mjs +1 -1
- package/dist/publish-contract-cli.cjs +2 -2
- package/dist/publish-contract-cli.cjs.map +1 -1
- package/dist/publish-contract-cli.mjs +2 -2
- package/dist/publish-contract-cli.mjs.map +1 -1
- package/dist/quarantine-cli.cjs +1 -1
- package/dist/quarantine-cli.mjs +1 -1
- package/dist/quarantine-policy2.cjs +2 -2
- package/dist/quarantine-policy2.mjs +2 -2
- package/dist/rust-policy-cli.cjs +481 -0
- package/dist/rust-policy-cli.cjs.map +1 -0
- package/dist/rust-policy-cli.d.cts +1 -0
- package/dist/rust-policy-cli.d.mts +1 -0
- package/dist/rust-policy-cli.mjs +479 -0
- package/dist/rust-policy-cli.mjs.map +1 -0
- package/dist/toolchain-changed-cli.cjs +1 -1
- package/dist/toolchain-changed-cli.mjs +1 -1
- package/dist/toolchain-dependabot.cjs +1 -1
- package/dist/toolchain-dependabot.mjs +2 -2
- package/dist/toolchain-dependabot.mjs.map +1 -1
- package/dist/toolchain-guard.cjs +5 -5
- package/dist/toolchain-guard.mjs +4 -4
- package/dist/toolchain-inputs.cjs +96 -17
- package/dist/toolchain-inputs.cjs.map +1 -1
- package/dist/toolchain-inputs.mjs +90 -17
- package/dist/toolchain-inputs.mjs.map +1 -1
- package/dist/toolchain-schema.cjs +6 -2
- package/dist/toolchain-schema.cjs.map +1 -1
- package/dist/toolchain-schema.mjs +6 -2
- package/dist/toolchain-schema.mjs.map +1 -1
- package/package.json +4 -3
- package/toolchain.json +12 -0
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const require_rolldown_runtime = require("./rolldown-runtime.cjs");
|
|
4
|
+
const require_generated_file = require("./generated-file.cjs");
|
|
5
|
+
let node_fs_promises = require("node:fs/promises");
|
|
6
|
+
let node_path = require("node:path");
|
|
7
|
+
let smol_toml = require("smol-toml");
|
|
8
|
+
let picomatch = require("picomatch");
|
|
9
|
+
picomatch = require_rolldown_runtime.__toESM(picomatch, 1);
|
|
10
|
+
//#region src/rust-policy-ownership.ts
|
|
11
|
+
const marker = "# stll-rust-policy-owned-v1: ";
|
|
12
|
+
const markerPrefix = "# stll-rust-policy-owned-";
|
|
13
|
+
const record$2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14
|
+
/** Arrays are policy values; inline TOML tables expose individually owned leaves. */
|
|
15
|
+
const policyLeaves = (table, prefix = []) => Object.entries(table).sort(([left], [right]) => left.localeCompare(right)).flatMap(([key, value]) => record$2(value) ? policyLeaves(value, [...prefix, key]) : [[...prefix, key]]);
|
|
16
|
+
const inManagedScope = (file, path) => {
|
|
17
|
+
if (file === "rustfmt.toml" || file === "clippy.toml") return path.length === 1;
|
|
18
|
+
if (file === ".cargo/config.toml") return path.length === 2 && path.at(0) === "alias";
|
|
19
|
+
if (!file.endsWith("Cargo.toml")) return false;
|
|
20
|
+
const root = file === "Cargo.toml";
|
|
21
|
+
if (root && path.at(0) === "profile") return path.length === 3 && [
|
|
22
|
+
"release",
|
|
23
|
+
"dev",
|
|
24
|
+
"ci"
|
|
25
|
+
].includes(path.at(1) ?? "");
|
|
26
|
+
const lintPath = path.at(0) === "workspace" && root ? path.slice(1) : path;
|
|
27
|
+
if (lintPath.at(0) !== "lints") return false;
|
|
28
|
+
if (lintPath.length === 2) return lintPath.at(1) === "workspace";
|
|
29
|
+
if (![
|
|
30
|
+
"rust",
|
|
31
|
+
"rustdoc",
|
|
32
|
+
"clippy"
|
|
33
|
+
].includes(lintPath.at(1) ?? "")) return false;
|
|
34
|
+
return lintPath.length === 3 || lintPath.length === 4 && ["level", "priority"].includes(lintPath.at(3) ?? "");
|
|
35
|
+
};
|
|
36
|
+
const validatePaths = (file, input) => {
|
|
37
|
+
if (!Array.isArray(input)) throw new Error("invalid Rust ownership metadata");
|
|
38
|
+
const paths = input.map((entry) => {
|
|
39
|
+
if (!Array.isArray(entry) || entry.length === 0 || !entry.every((part) => typeof part === "string" && /^[A-Za-z0-9_-]+$/.test(part) && ![
|
|
40
|
+
"__proto__",
|
|
41
|
+
"constructor",
|
|
42
|
+
"prototype"
|
|
43
|
+
].includes(part))) throw new Error("invalid Rust ownership path");
|
|
44
|
+
const path = entry.map((part) => {
|
|
45
|
+
if (typeof part !== "string") throw new Error("invalid ownership path");
|
|
46
|
+
return part;
|
|
47
|
+
});
|
|
48
|
+
if (!inManagedScope(file, path)) throw new Error(`Rust ownership metadata escapes managed scope: ${file}`);
|
|
49
|
+
return path;
|
|
50
|
+
});
|
|
51
|
+
const seen = /* @__PURE__ */ new Set();
|
|
52
|
+
for (const path of paths) {
|
|
53
|
+
const key = JSON.stringify(path);
|
|
54
|
+
if (seen.has(key)) throw new Error("duplicate Rust ownership path");
|
|
55
|
+
seen.add(key);
|
|
56
|
+
for (let length = 1; length < path.length; length++) if (paths.some((other) => JSON.stringify(other) === JSON.stringify(path.slice(0, length)))) throw new Error("overlapping Rust ownership paths");
|
|
57
|
+
}
|
|
58
|
+
return paths;
|
|
59
|
+
};
|
|
60
|
+
const ownershipHeader = (file, owned) => {
|
|
61
|
+
const paths = policyLeaves(owned).filter((path) => JSON.stringify(path) !== "[\"workspace\",\"resolver\"]");
|
|
62
|
+
validatePaths(file, paths);
|
|
63
|
+
return `${marker}${JSON.stringify(paths)}\n`;
|
|
64
|
+
};
|
|
65
|
+
const removeLeaf = (table, path) => {
|
|
66
|
+
const key = path.at(0);
|
|
67
|
+
if (key === void 0 || !Object.hasOwn(table, key)) return;
|
|
68
|
+
const value = table[key];
|
|
69
|
+
if (path.length === 1) {
|
|
70
|
+
if (record$2(value)) throw new Error("Rust ownership leaf became a table; resolve ownership explicitly");
|
|
71
|
+
Reflect.deleteProperty(table, key);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (!record$2(value)) throw new Error("Rust ownership table became a value; resolve ownership explicitly");
|
|
75
|
+
removeLeaf(value, path.slice(1));
|
|
76
|
+
if (Object.keys(value).length === 0) Reflect.deleteProperty(table, key);
|
|
77
|
+
};
|
|
78
|
+
const previousPolicyPaths = (file, current) => {
|
|
79
|
+
const declarations = [];
|
|
80
|
+
for (const line of (current ?? "").split("\n")) {
|
|
81
|
+
if (line.trim() !== "" && !line.startsWith("#")) break;
|
|
82
|
+
if (line.startsWith(markerPrefix)) declarations.push(line);
|
|
83
|
+
}
|
|
84
|
+
if (declarations.length === 0) return void 0;
|
|
85
|
+
const declaration = declarations.at(0);
|
|
86
|
+
if (declarations.length !== 1 || declaration === void 0 || !declaration.startsWith(marker)) throw new Error("invalid Rust ownership metadata version or count");
|
|
87
|
+
return validatePaths(file, JSON.parse(declaration.slice(29)));
|
|
88
|
+
};
|
|
89
|
+
const removePreviousPolicy = (file, current, document) => {
|
|
90
|
+
for (const path of previousPolicyPaths(file, current) ?? []) removeLeaf(document, path);
|
|
91
|
+
};
|
|
92
|
+
const removePreviousMemberPolicy = (file, current, document) => {
|
|
93
|
+
const paths = previousPolicyPaths(file, current);
|
|
94
|
+
if (paths === void 0) {
|
|
95
|
+
const lints = document["lints"];
|
|
96
|
+
if (record$2(lints) && Object.hasOwn(lints, "workspace")) throw new Error(`retired member must retain its generated inheritance ownership: ${file}`);
|
|
97
|
+
return "unmanaged";
|
|
98
|
+
}
|
|
99
|
+
if (paths.some((path) => JSON.stringify(path) !== "[\"lints\",\"workspace\"]")) throw new Error(`retired member must retain its generated inheritance ownership: ${file}`);
|
|
100
|
+
for (const path of paths) removeLeaf(document, path);
|
|
101
|
+
return "owned";
|
|
102
|
+
};
|
|
103
|
+
const memberMarker = "# stll-rust-policy-members-v1: ";
|
|
104
|
+
const memberPrefix = "# stll-rust-policy-members-";
|
|
105
|
+
const memberPaths = (input) => {
|
|
106
|
+
if (!Array.isArray(input)) throw new Error("invalid Rust member ownership index");
|
|
107
|
+
const paths = input.map((value) => {
|
|
108
|
+
if (typeof value !== "string" || value === "Cargo.toml" || !value.endsWith("/Cargo.toml") || value.includes("\\") || /\p{Cc}/u.test(value) || /^[A-Za-z]:/u.test(value) || value.split("/").some((part) => part === "." || part === ".." || part === "")) throw new Error("Rust member ownership paths must be canonical repository Cargo.toml paths");
|
|
109
|
+
return value;
|
|
110
|
+
});
|
|
111
|
+
if (new Set(paths).size !== paths.length) throw new Error("duplicate Rust member ownership path");
|
|
112
|
+
return paths;
|
|
113
|
+
};
|
|
114
|
+
const previousMemberPaths = (source) => {
|
|
115
|
+
const declarations = [];
|
|
116
|
+
for (const line of source.split("\n")) {
|
|
117
|
+
if (line.trim() !== "" && !line.startsWith("#")) break;
|
|
118
|
+
if (line.startsWith(memberPrefix)) declarations.push(line);
|
|
119
|
+
}
|
|
120
|
+
if (declarations.length === 0) return [];
|
|
121
|
+
const declaration = declarations.at(0);
|
|
122
|
+
if (declarations.length !== 1 || declaration === void 0 || !declaration.startsWith(memberMarker)) throw new Error("invalid Rust member ownership index version or count");
|
|
123
|
+
return memberPaths(JSON.parse(declaration.slice(31)));
|
|
124
|
+
};
|
|
125
|
+
const memberOwnershipHeader = (members) => `${memberMarker}${JSON.stringify(memberPaths(members.filter((file) => file !== "Cargo.toml")))}\n`;
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region src/rust-workspace-members.ts
|
|
128
|
+
const record$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
129
|
+
const patterns = (value) => {
|
|
130
|
+
if (value === void 0) return [];
|
|
131
|
+
if (!Array.isArray(value)) throw new Error("workspace members/exclude must be arrays");
|
|
132
|
+
return value.map((entry) => {
|
|
133
|
+
if (typeof entry !== "string" || entry.length === 0 || entry.startsWith("/") || entry.includes("\\") || entry.split("/").includes("..")) throw new Error("workspace patterns must remain inside the repository");
|
|
134
|
+
return node_path.posix.normalize(entry);
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
const checkRealAncestors = async (root, directory) => {
|
|
138
|
+
let parent = root;
|
|
139
|
+
for (const component of directory.split("/").filter((part) => part !== "." && part !== "")) {
|
|
140
|
+
parent = (0, node_path.join)(parent, component);
|
|
141
|
+
await require_generated_file.checkGeneratedOutput((0, node_path.join)(parent, ".stll-path-check"));
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const safeManifest = async (root, directory) => {
|
|
145
|
+
await checkRealAncestors(root, directory);
|
|
146
|
+
const path = (0, node_path.join)(root, directory, "Cargo.toml");
|
|
147
|
+
return await require_generated_file.checkGeneratedOutput(path) === void 0 ? void 0 : (0, smol_toml.parse)(await (0, node_fs_promises.readFile)(path, "utf8"));
|
|
148
|
+
};
|
|
149
|
+
/** Keep globstar states alive while consuming only actual directory components. */
|
|
150
|
+
const memberPrefixMatcher = (pattern) => {
|
|
151
|
+
const segments = pattern.split("/");
|
|
152
|
+
const uncertain = segments.findIndex((segment) => {
|
|
153
|
+
const closing = [];
|
|
154
|
+
for (const character of segment) {
|
|
155
|
+
if (closing.at(-1) === "]") {
|
|
156
|
+
if (character === "]") closing.pop();
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (character === "[") closing.push("]");
|
|
160
|
+
else if (character === "{") closing.push("}");
|
|
161
|
+
else if (character === "(") closing.push(")");
|
|
162
|
+
else if (character === closing.at(-1)) closing.pop();
|
|
163
|
+
}
|
|
164
|
+
return closing.length > 0;
|
|
165
|
+
});
|
|
166
|
+
const matchers = segments.map((segment) => (0, picomatch.default)(segment, { dot: true }));
|
|
167
|
+
return (directory) => {
|
|
168
|
+
if (pattern.startsWith("!") && !pattern.startsWith("!(")) return true;
|
|
169
|
+
let states = /* @__PURE__ */ new Set([0]);
|
|
170
|
+
const expand = () => {
|
|
171
|
+
for (const state of states) if (segments[state] === "**") states.add(state + 1);
|
|
172
|
+
};
|
|
173
|
+
expand();
|
|
174
|
+
for (const component of directory === "." ? [] : directory.split("/")) {
|
|
175
|
+
if (uncertain >= 0 && states.has(uncertain)) return true;
|
|
176
|
+
const next = /* @__PURE__ */ new Set();
|
|
177
|
+
for (const state of states) if (segments[state] === "**") next.add(state);
|
|
178
|
+
else if (matchers[state]?.(component)) next.add(state + 1);
|
|
179
|
+
states = next;
|
|
180
|
+
expand();
|
|
181
|
+
}
|
|
182
|
+
return states.size > 0;
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
/** Expand only declared member subtrees, then follow in-tree path dependencies. */
|
|
186
|
+
const rustWorkspaceMembers = async (root, manifest) => {
|
|
187
|
+
const workspace = manifest["workspace"];
|
|
188
|
+
if (!record$1(workspace)) throw new Error("workspace kind requires a workspace manifest");
|
|
189
|
+
const declaredMembers = patterns(workspace["members"]);
|
|
190
|
+
const excludes = patterns(workspace["exclude"]);
|
|
191
|
+
const within = (directory, prefix) => prefix === "." || directory === prefix || directory.startsWith(`${prefix}/`);
|
|
192
|
+
const excluded = (directory) => excludes.some((prefix) => within(directory, prefix)) && !declaredMembers.some((prefix) => within(directory, prefix));
|
|
193
|
+
const excludedSubtree = (directory) => excluded(directory) && !declaredMembers.some((member) => within(member, directory));
|
|
194
|
+
const members = /* @__PURE__ */ new Map();
|
|
195
|
+
if (record$1(manifest["package"])) members.set(".", manifest);
|
|
196
|
+
for (const pattern of declaredMembers) {
|
|
197
|
+
const scan = picomatch.default.scan(pattern);
|
|
198
|
+
if (!scan.isGlob) {
|
|
199
|
+
if (excluded(pattern)) continue;
|
|
200
|
+
const member = await safeManifest(root, pattern);
|
|
201
|
+
if (member === void 0) throw new Error(`missing workspace member: ${pattern}`);
|
|
202
|
+
members.set(pattern, member);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const outcome = {
|
|
206
|
+
matches: 0,
|
|
207
|
+
prunedExclusion: false
|
|
208
|
+
};
|
|
209
|
+
const canContainMember = memberPrefixMatcher(pattern);
|
|
210
|
+
const maximumDepth = pattern.includes("**") ? Infinity : pattern.split("/").length;
|
|
211
|
+
const walk = async (directory) => {
|
|
212
|
+
const depth = directory === "." ? 0 : directory.split("/").length;
|
|
213
|
+
if (!canContainMember(directory)) return;
|
|
214
|
+
if (excludedSubtree(directory)) {
|
|
215
|
+
outcome.prunedExclusion = true;
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (picomatch.default.isMatch(directory, pattern, { dot: true })) {
|
|
219
|
+
outcome.matches++;
|
|
220
|
+
if (!excluded(directory)) {
|
|
221
|
+
const member = await safeManifest(root, directory);
|
|
222
|
+
if (member === void 0) throw new Error(`missing workspace member manifest: ${directory}`);
|
|
223
|
+
members.set(directory, member);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (depth >= maximumDepth) return;
|
|
227
|
+
await checkRealAncestors(root, directory);
|
|
228
|
+
for (const entry of await (0, node_fs_promises.readdir)((0, node_path.join)(root, directory), { withFileTypes: true })) {
|
|
229
|
+
const child = node_path.posix.join(directory, entry.name);
|
|
230
|
+
if (!canContainMember(child)) continue;
|
|
231
|
+
if (excludedSubtree(child)) {
|
|
232
|
+
outcome.prunedExclusion = true;
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
if (entry.isSymbolicLink()) {
|
|
236
|
+
if ((await (0, node_fs_promises.stat)((0, node_path.join)(root, child))).isDirectory()) throw new Error("workspace members must use real directories");
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
if (entry.isDirectory()) await walk(child);
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
await walk(scan.base || ".");
|
|
243
|
+
if (outcome.matches === 0 && !outcome.prunedExclusion) throw new Error(`workspace pattern matched no manifests: ${pattern}`);
|
|
244
|
+
}
|
|
245
|
+
const inherited = workspace["dependencies"];
|
|
246
|
+
for (const [directory, member] of members) {
|
|
247
|
+
const owners = [member];
|
|
248
|
+
const targets = member["target"];
|
|
249
|
+
if (record$1(targets)) {
|
|
250
|
+
for (const target of Object.values(targets)) if (record$1(target)) owners.push(target);
|
|
251
|
+
}
|
|
252
|
+
for (const owner of owners) for (const key of [
|
|
253
|
+
"dependencies",
|
|
254
|
+
"dev-dependencies",
|
|
255
|
+
"build-dependencies"
|
|
256
|
+
]) {
|
|
257
|
+
const dependencies = owner[key];
|
|
258
|
+
if (!record$1(dependencies)) continue;
|
|
259
|
+
for (const [name, dependency] of Object.entries(dependencies)) {
|
|
260
|
+
if (!record$1(dependency)) continue;
|
|
261
|
+
const isInherited = dependency["workspace"] === true;
|
|
262
|
+
const resolved = isInherited && record$1(inherited) ? inherited[name] : dependency;
|
|
263
|
+
if (!record$1(resolved) || typeof resolved["path"] !== "string") continue;
|
|
264
|
+
if (node_path.posix.isAbsolute(resolved["path"]) || resolved["path"].includes("\\")) throw new Error("path dependencies must use portable relative paths");
|
|
265
|
+
const target = node_path.posix.normalize(node_path.posix.join(isInherited ? "." : directory, resolved["path"]));
|
|
266
|
+
if (target === ".." || target.startsWith("../") || excluded(target) || members.has(target)) continue;
|
|
267
|
+
const parsed = await safeManifest(root, target);
|
|
268
|
+
if (parsed === void 0) throw new Error(`missing path dependency manifest: ${target}`);
|
|
269
|
+
members.set(target, parsed);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return [...members.keys()].sort().map((directory) => node_path.posix.join(directory, "Cargo.toml"));
|
|
274
|
+
};
|
|
275
|
+
//#endregion
|
|
276
|
+
//#region src/rust-policy.ts
|
|
277
|
+
const record = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
278
|
+
const keys = (value, allowed) => {
|
|
279
|
+
if (Object.keys(value).some((key) => !allowed.includes(key))) throw new Error("unknown Rust policy input field");
|
|
280
|
+
};
|
|
281
|
+
const parseRustPolicy = (input) => {
|
|
282
|
+
if (!record(input)) throw new Error("Rust policy input must be an object");
|
|
283
|
+
keys(input, ["kind", "exceptions"]);
|
|
284
|
+
if (input["kind"] !== "single-crate" && input["kind"] !== "workspace") throw new Error("kind must be single-crate or workspace");
|
|
285
|
+
const exceptions = input["exceptions"] ?? [];
|
|
286
|
+
if (!Array.isArray(exceptions)) throw new Error("exceptions must be an array");
|
|
287
|
+
const parsedExceptions = exceptions.map((entry) => {
|
|
288
|
+
if (!record(entry)) throw new Error("exception must be an object");
|
|
289
|
+
keys(entry, [
|
|
290
|
+
"file",
|
|
291
|
+
"path",
|
|
292
|
+
"value",
|
|
293
|
+
"reason"
|
|
294
|
+
]);
|
|
295
|
+
if (typeof entry["file"] !== "string" || !Array.isArray(entry["path"]) || entry["path"].length === 0 || !entry["path"].every((part) => typeof part === "string" && part.length > 0) || !("value" in entry) || typeof entry["reason"] !== "string" || entry["reason"].trim().length === 0) throw new Error("exceptions require file, nonempty path, value and reason");
|
|
296
|
+
const path = entry["path"].map((part) => {
|
|
297
|
+
if (typeof part !== "string") throw new Error("invalid exception path");
|
|
298
|
+
return part;
|
|
299
|
+
});
|
|
300
|
+
return {
|
|
301
|
+
file: entry["file"],
|
|
302
|
+
path,
|
|
303
|
+
value: entry["value"]
|
|
304
|
+
};
|
|
305
|
+
});
|
|
306
|
+
return {
|
|
307
|
+
kind: input["kind"],
|
|
308
|
+
exceptions: parsedExceptions
|
|
309
|
+
};
|
|
310
|
+
};
|
|
311
|
+
const merge = (target, policy) => {
|
|
312
|
+
for (const [key, value] of Object.entries(policy)) {
|
|
313
|
+
if (!record(value)) {
|
|
314
|
+
target[key] = value;
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
const existing = target[key];
|
|
318
|
+
if (existing !== void 0 && !record(existing)) throw new Error(`policy table conflicts with value: ${key}`);
|
|
319
|
+
const table = record(existing) ? existing : {};
|
|
320
|
+
merge(table, value);
|
|
321
|
+
target[key] = table;
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
const requirePolicyTable = (value) => {
|
|
325
|
+
if (!record(value)) throw new Error("exception path must name an existing policy value");
|
|
326
|
+
return value;
|
|
327
|
+
};
|
|
328
|
+
const template = async (name) => {
|
|
329
|
+
const text = {
|
|
330
|
+
"cargo-root.toml": "# Source template for stll-rust-policy single-crate manifests.\n\n[lints.rust]\nwarnings = { level = \"deny\", priority = -1 }\ndead_code = \"deny\"\nfuture_incompatible = { level = \"deny\", priority = -1 }\nnonstandard_style = { level = \"deny\", priority = -1 }\nrust_2018_idioms = { level = \"deny\", priority = -1 }\nunreachable_code = \"deny\"\nunreachable_patterns = \"deny\"\nunreachable_pub = \"deny\"\nunsafe_code = \"deny\"\nunused_imports = \"deny\"\nunused_macros = \"deny\"\nunused_mut = \"deny\"\nunused_variables = \"deny\"\n\n[lints.rustdoc]\nbroken_intra_doc_links = \"deny\"\nbare_urls = \"deny\"\n\n[lints.clippy]\nall = { level = \"deny\", priority = -1 }\npedantic = { level = \"warn\", priority = -1 }\ncargo = { level = \"warn\", priority = -1 }\nnursery = { level = \"warn\", priority = -1 }\n\ndbg_macro = \"deny\"\ntodo = \"deny\"\nunimplemented = \"deny\"\npanic = \"deny\"\nunwrap_used = \"deny\"\nexpect_used = \"deny\"\nindexing_slicing = \"warn\"\ninteger_division = \"warn\"\narithmetic_side_effects = \"warn\"\nas_conversions = \"warn\"\ncast_possible_truncation = \"warn\"\ncast_possible_wrap = \"warn\"\ncast_precision_loss = \"warn\"\ncast_sign_loss = \"warn\"\nclone_on_ref_ptr = \"deny\"\ncreate_dir = \"deny\"\ndecimal_literal_representation = \"warn\"\nderive_partial_eq_without_eq = \"deny\"\ndisallowed_macros = \"deny\"\ndisallowed_methods = \"deny\"\ndisallowed_types = \"deny\"\nempty_enum_variants_with_brackets = \"deny\"\nempty_structs_with_brackets = \"deny\"\nenum_glob_use = \"deny\"\nexit = \"deny\"\nfiletype_is_file = \"deny\"\nfloat_cmp = \"warn\"\nfn_to_numeric_cast_any = \"deny\"\nformat_collect = \"deny\"\nif_then_some_else_none = \"deny\"\nimplicit_clone = \"deny\"\ninefficient_to_string = \"deny\"\nlarge_enum_variant = \"deny\"\nlarge_stack_arrays = \"deny\"\nlarge_stack_frames = \"deny\"\nmanual_let_else = \"deny\"\nmanual_memcpy = \"deny\"\nmap_unwrap_or = \"deny\"\nmem_forget = \"deny\"\nmissing_assert_message = \"warn\"\nmissing_errors_doc = \"allow\"\nmissing_panics_doc = \"allow\"\nmodule_name_repetitions = \"allow\"\nmultiple_crate_versions = \"allow\"\nneedless_collect = \"deny\"\nneedless_continue = \"deny\"\nneedless_pass_by_ref_mut = \"deny\"\nneedless_pass_by_value = \"deny\"\nor_fun_call = \"deny\"\nprint_stderr = \"deny\"\nprint_stdout = \"deny\"\nredundant_clone = \"deny\"\nsame_name_method = \"deny\"\nself_named_module_files = \"allow\"\nsemicolon_if_nothing_returned = \"deny\"\nshadow_reuse = \"allow\"\nshadow_same = \"warn\"\nshadow_unrelated = \"warn\"\nstd_instead_of_alloc = \"allow\"\nstd_instead_of_core = \"allow\"\nstring_slice = \"warn\"\ntests_outside_test_module = \"allow\"\ntrivially_copy_pass_by_ref = \"deny\"\nunnecessary_wraps = \"deny\"\nunneeded_field_pattern = \"deny\"\nunreachable = \"deny\"\nunused_async = \"deny\"\nunused_self = \"deny\"\nuse_self = \"warn\"\nused_underscore_binding = \"deny\"\nverbose_file_reads = \"deny\"\nwildcard_imports = \"deny\"\n\n[profile.release]\nlto = \"fat\"\ncodegen-units = 1\npanic = \"abort\"\nstrip = \"symbols\"\n\n[profile.dev]\ndebug = \"line-tables-only\"\n\n[profile.ci]\ninherits = \"dev\"\ndebug-assertions = true\noverflow-checks = true\n",
|
|
331
|
+
"cargo-workspace.toml": "# Source template for stll-rust-policy workspace manifests.\n# The generator adds lint inheritance to discovered member manifests.\n\n[workspace]\nresolver = \"2\"\n\n[workspace.lints.rust]\nwarnings = { level = \"deny\", priority = -1 }\ndead_code = \"deny\"\nfuture_incompatible = { level = \"deny\", priority = -1 }\nnonstandard_style = { level = \"deny\", priority = -1 }\nrust_2018_idioms = { level = \"deny\", priority = -1 }\nunreachable_code = \"deny\"\nunreachable_patterns = \"deny\"\nunreachable_pub = \"deny\"\nunsafe_code = \"deny\"\nunused_imports = \"deny\"\nunused_macros = \"deny\"\nunused_mut = \"deny\"\nunused_variables = \"deny\"\n\n[workspace.lints.rustdoc]\nbroken_intra_doc_links = \"deny\"\nbare_urls = \"deny\"\n\n[workspace.lints.clippy]\nall = { level = \"deny\", priority = -1 }\npedantic = { level = \"warn\", priority = -1 }\ncargo = { level = \"warn\", priority = -1 }\nnursery = { level = \"warn\", priority = -1 }\n\ndbg_macro = \"deny\"\ntodo = \"deny\"\nunimplemented = \"deny\"\npanic = \"deny\"\nunwrap_used = \"deny\"\nexpect_used = \"deny\"\nindexing_slicing = \"warn\"\ninteger_division = \"warn\"\narithmetic_side_effects = \"warn\"\nas_conversions = \"warn\"\ncast_possible_truncation = \"warn\"\ncast_possible_wrap = \"warn\"\ncast_precision_loss = \"warn\"\ncast_sign_loss = \"warn\"\nclone_on_ref_ptr = \"deny\"\ncreate_dir = \"deny\"\ndecimal_literal_representation = \"warn\"\nderive_partial_eq_without_eq = \"deny\"\ndisallowed_macros = \"deny\"\ndisallowed_methods = \"deny\"\ndisallowed_types = \"deny\"\nempty_enum_variants_with_brackets = \"deny\"\nempty_structs_with_brackets = \"deny\"\nenum_glob_use = \"deny\"\nexit = \"deny\"\nfiletype_is_file = \"deny\"\nfloat_cmp = \"warn\"\nfn_to_numeric_cast_any = \"deny\"\nformat_collect = \"deny\"\nif_then_some_else_none = \"deny\"\nimplicit_clone = \"deny\"\ninefficient_to_string = \"deny\"\nlarge_enum_variant = \"deny\"\nlarge_stack_arrays = \"deny\"\nlarge_stack_frames = \"deny\"\nmanual_let_else = \"deny\"\nmanual_memcpy = \"deny\"\nmap_unwrap_or = \"deny\"\nmem_forget = \"deny\"\nmissing_assert_message = \"warn\"\nmissing_errors_doc = \"allow\"\nmissing_panics_doc = \"allow\"\nmodule_name_repetitions = \"allow\"\nmultiple_crate_versions = \"allow\"\nneedless_collect = \"deny\"\nneedless_continue = \"deny\"\nneedless_pass_by_ref_mut = \"deny\"\nneedless_pass_by_value = \"deny\"\nor_fun_call = \"deny\"\nprint_stderr = \"deny\"\nprint_stdout = \"deny\"\nredundant_clone = \"deny\"\nsame_name_method = \"deny\"\nself_named_module_files = \"allow\"\nsemicolon_if_nothing_returned = \"deny\"\nshadow_reuse = \"allow\"\nshadow_same = \"warn\"\nshadow_unrelated = \"warn\"\nstd_instead_of_alloc = \"allow\"\nstd_instead_of_core = \"allow\"\nstring_slice = \"warn\"\ntests_outside_test_module = \"allow\"\ntrivially_copy_pass_by_ref = \"deny\"\nunnecessary_wraps = \"deny\"\nunneeded_field_pattern = \"deny\"\nunreachable = \"deny\"\nunused_async = \"deny\"\nunused_self = \"deny\"\nuse_self = \"warn\"\nused_underscore_binding = \"deny\"\nverbose_file_reads = \"deny\"\nwildcard_imports = \"deny\"\n\n[profile.release]\nlto = \"fat\"\ncodegen-units = 1\npanic = \"abort\"\nstrip = \"symbols\"\n\n[profile.dev]\ndebug = \"line-tables-only\"\n\n[profile.ci]\ninherits = \"dev\"\ndebug-assertions = true\noverflow-checks = true\n",
|
|
332
|
+
"cargo-config.toml": "# Source template for stll-rust-policy Cargo aliases.\n\n[alias]\nci-fmt = \"fmt --all -- --check\"\nci-clippy = \"clippy --workspace --all-targets --all-features --locked -- -D warnings\"\nci-stella-lint = \"stella-lint .\"\nci-test = \"test --workspace --all-features --locked\"\n",
|
|
333
|
+
"rustfmt.toml": "edition = \"2024\"\nmax_width = 80\nreorder_imports = true\ntab_spaces = 2\n",
|
|
334
|
+
"clippy.toml": "# Portable stella Rust lint configuration. Keep repo-specific wrappers and\n# exceptions in consuming repositories.\n\ndisallowed-macros = [\n { path = \"std::dbg\", reason = \"remove debug output before commit\" },\n { path = \"std::print\", reason = \"library crates should return data or use structured logging\" },\n { path = \"std::println\", reason = \"library crates should return data or use structured logging\" },\n { path = \"std::eprint\", reason = \"library crates should return data or use structured logging\" },\n { path = \"std::eprintln\", reason = \"library crates should return data or use structured logging\" },\n]\n\ndisallowed-methods = [\n { path = \"std::mem::forget\", reason = \"leaks ownership; use a narrow ownership type or ManuallyDrop with justification\" },\n { path = \"std::string::String::from_utf8_lossy\", reason = \"lossy decoding can corrupt offsets and user data; validate or keep bytes\" },\n]\n\ndisallowed-types = [\n { path = \"std::collections::LinkedList\", reason = \"prefer Vec, VecDeque, or an explicit intrusive structure\" },\n]\n\npass-by-value-size-limit = 64\nstack-size-threshold = 131072\nenum-variant-size-threshold = 128\ntoo-large-for-stack = 4096\navoid-breaking-exported-api = false\naccept-comment-above-attributes = true\n"
|
|
335
|
+
}[name];
|
|
336
|
+
if (text === void 0) throw new Error(`missing Rust template: ${name}`);
|
|
337
|
+
return (0, smol_toml.parse)(text);
|
|
338
|
+
};
|
|
339
|
+
const optionalText = async (path) => {
|
|
340
|
+
try {
|
|
341
|
+
return await (0, node_fs_promises.readFile)(path, "utf8");
|
|
342
|
+
} catch (error) {
|
|
343
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") return void 0;
|
|
344
|
+
throw error;
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
const generateRustPolicy = async ({ root, input, mode }) => {
|
|
348
|
+
const policy = parseRustPolicy(input);
|
|
349
|
+
const repository = await (0, node_fs_promises.realpath)(root);
|
|
350
|
+
await require_generated_file.checkGeneratedOutput((0, node_path.join)(repository, "Cargo.toml"));
|
|
351
|
+
const rootSource = await (0, node_fs_promises.readFile)((0, node_path.join)(repository, "Cargo.toml"), "utf8");
|
|
352
|
+
const manifest = (0, smol_toml.parse)(rootSource);
|
|
353
|
+
const previousMembers = previousMemberPaths(rootSource);
|
|
354
|
+
const members = policy.kind === "workspace" ? await rustWorkspaceMembers(repository, manifest) : [];
|
|
355
|
+
const cargoPolicy = await template(policy.kind === "workspace" ? "cargo-workspace.toml" : "cargo-root.toml");
|
|
356
|
+
const workspace = manifest["workspace"];
|
|
357
|
+
const generatedWorkspace = cargoPolicy["workspace"];
|
|
358
|
+
if (record(workspace) && record(generatedWorkspace) && workspace["resolver"] !== void 0) generatedWorkspace["resolver"] = workspace["resolver"];
|
|
359
|
+
const outputs = /* @__PURE__ */ new Map([
|
|
360
|
+
["Cargo.toml", cargoPolicy],
|
|
361
|
+
[".cargo/config.toml", await template("cargo-config.toml")],
|
|
362
|
+
["rustfmt.toml", await template("rustfmt.toml")],
|
|
363
|
+
["clippy.toml", await template("clippy.toml")]
|
|
364
|
+
]);
|
|
365
|
+
for (const member of members) {
|
|
366
|
+
if (member === "Cargo.toml") {
|
|
367
|
+
merge(cargoPolicy, { lints: { workspace: true } });
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
outputs.set(member, { lints: { workspace: true } });
|
|
371
|
+
}
|
|
372
|
+
const seen = /* @__PURE__ */ new Set();
|
|
373
|
+
for (const exception of policy.exceptions) {
|
|
374
|
+
const signature = JSON.stringify([exception.file, exception.path]);
|
|
375
|
+
if (seen.has(signature)) throw new Error("duplicate Rust policy exception");
|
|
376
|
+
seen.add(signature);
|
|
377
|
+
let table = outputs.get(exception.file);
|
|
378
|
+
if (table === void 0) throw new Error("exception file is not a generated output");
|
|
379
|
+
if (exception.path.length === 2 && exception.path.at(0) === "lints" && exception.path.at(1) === "workspace") throw new Error("workspace lint inheritance is structural and cannot be excepted");
|
|
380
|
+
const last = exception.path.at(-1);
|
|
381
|
+
for (const key of exception.path.slice(0, -1)) {
|
|
382
|
+
if (!Object.hasOwn(table, key)) throw new Error("exception path must name an existing policy value");
|
|
383
|
+
table = requirePolicyTable(table[key]);
|
|
384
|
+
}
|
|
385
|
+
if (last === void 0 || !Object.hasOwn(table, last) || record(table[last])) throw new Error("exception must replace a policy leaf");
|
|
386
|
+
const previous = table[last];
|
|
387
|
+
if (typeof previous !== typeof exception.value || Array.isArray(previous) !== Array.isArray(exception.value) || exception.value === null) throw new Error("exception must preserve the policy value type");
|
|
388
|
+
table[last] = exception.value;
|
|
389
|
+
}
|
|
390
|
+
const plans = [];
|
|
391
|
+
const retired = previousMembers.filter((file) => !outputs.has(file));
|
|
392
|
+
for (const file of [...outputs.keys(), ...retired]) {
|
|
393
|
+
const owned = outputs.get(file);
|
|
394
|
+
const destination = (0, node_path.join)(repository, file);
|
|
395
|
+
let parent = repository;
|
|
396
|
+
for (const segment of file.split("/").slice(0, -1)) {
|
|
397
|
+
parent = (0, node_path.join)(parent, segment);
|
|
398
|
+
await require_generated_file.checkGeneratedOutput((0, node_path.join)(parent, ".stll-path-check"));
|
|
399
|
+
}
|
|
400
|
+
const stat = await require_generated_file.checkGeneratedOutput(destination);
|
|
401
|
+
const current = await optionalText(destination);
|
|
402
|
+
if (owned === void 0 && current === void 0) continue;
|
|
403
|
+
if (file.endsWith("Cargo.toml") && current === void 0) throw new Error(`missing manifest: ${file}`);
|
|
404
|
+
const document = current === void 0 ? {} : (0, smol_toml.parse)(current);
|
|
405
|
+
if (file.endsWith("Cargo.toml")) {
|
|
406
|
+
const lints = document["lints"];
|
|
407
|
+
if (policy.kind === "workspace" && members.includes(file) && record(lints) && Object.keys(lints).some((key) => key !== "workspace")) throw new Error(`remove local lint tables before workspace inheritance: ${file}`);
|
|
408
|
+
if (file === "Cargo.toml" && policy.kind === "single-crate" && record(lints) && lints["workspace"] === true) throw new Error("single-crate lints cannot inherit workspace policy");
|
|
409
|
+
if (file === "Cargo.toml" && policy.kind === "workspace" && !record(document["workspace"])) throw new Error("workspace kind requires a workspace manifest");
|
|
410
|
+
if (file === "Cargo.toml" && policy.kind === "single-crate" && "workspace" in document) throw new Error("use workspace kind for workspace manifests");
|
|
411
|
+
}
|
|
412
|
+
if (owned === void 0) {
|
|
413
|
+
if (current === void 0) throw new Error("retired member source missing");
|
|
414
|
+
if (removePreviousMemberPolicy(file, current, document) === "unmanaged") continue;
|
|
415
|
+
} else {
|
|
416
|
+
removePreviousPolicy(file, current, document);
|
|
417
|
+
merge(document, owned);
|
|
418
|
+
}
|
|
419
|
+
const indexHeader = file === "Cargo.toml" ? memberOwnershipHeader(members) : "";
|
|
420
|
+
const text = `# Generated by stll-rust-policy; edit policy input for exceptions.\n${ownershipHeader(file, owned ?? {})}${indexHeader}${(0, smol_toml.stringify)(document)}`;
|
|
421
|
+
plans.push({
|
|
422
|
+
file,
|
|
423
|
+
destination,
|
|
424
|
+
text,
|
|
425
|
+
current,
|
|
426
|
+
mode: stat === void 0 ? 420 : stat.mode & 511
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
const drift = plans.filter(({ text, current }) => text !== current).map(({ file }) => file);
|
|
430
|
+
if (mode === "check") return drift;
|
|
431
|
+
const rootPlan = plans.find(({ file }) => file === "Cargo.toml");
|
|
432
|
+
if (rootPlan === void 0) throw new Error("root ownership plan missing");
|
|
433
|
+
const union = [.../* @__PURE__ */ new Set([...previousMembers, ...members])].sort();
|
|
434
|
+
const journalText = rootPlan.text.replace(memberOwnershipHeader(members), memberOwnershipHeader(union));
|
|
435
|
+
if (journalText !== rootPlan.current) await require_generated_file.writeGeneratedFile({
|
|
436
|
+
...rootPlan,
|
|
437
|
+
text: journalText
|
|
438
|
+
});
|
|
439
|
+
for (const plan of plans.filter(({ file }) => file !== "Cargo.toml")) if (plan.text !== plan.current) await require_generated_file.writeGeneratedFile(plan);
|
|
440
|
+
if (rootPlan.text !== journalText) await require_generated_file.writeGeneratedFile(rootPlan);
|
|
441
|
+
return drift;
|
|
442
|
+
};
|
|
443
|
+
//#endregion
|
|
444
|
+
//#region src/rust-policy-cli.ts
|
|
445
|
+
const usage = "Usage: stll-rust-policy [--check] [--config <path>]\nRun from the repository root; default input: stll-rust-policy.json";
|
|
446
|
+
const main = async () => {
|
|
447
|
+
const args = process.argv.slice(2);
|
|
448
|
+
if (args.length === 1 && args.at(0) === "--help") {
|
|
449
|
+
process.stdout.write(`${usage}\n`);
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
let mode = "write";
|
|
453
|
+
let config = "stll-rust-policy.json";
|
|
454
|
+
const seen = /* @__PURE__ */ new Set();
|
|
455
|
+
for (let index = 0; index < args.length; index++) {
|
|
456
|
+
const arg = args.at(index);
|
|
457
|
+
if (arg === void 0 || seen.has(arg)) throw new Error(usage);
|
|
458
|
+
seen.add(arg);
|
|
459
|
+
if (arg === "--check") {
|
|
460
|
+
mode = "check";
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
if (arg !== "--config") throw new Error(usage);
|
|
464
|
+
const path = args.at(++index);
|
|
465
|
+
if (path === void 0 || path.startsWith("--")) throw new Error(usage);
|
|
466
|
+
config = path;
|
|
467
|
+
}
|
|
468
|
+
const drift = await generateRustPolicy({
|
|
469
|
+
root: process.cwd(),
|
|
470
|
+
input: JSON.parse(await (0, node_fs_promises.readFile)(config, "utf8")),
|
|
471
|
+
mode
|
|
472
|
+
});
|
|
473
|
+
if (mode === "check" && drift.length > 0) throw new Error(`Rust policy drift: ${drift.join(", ")}; run stll-rust-policy`);
|
|
474
|
+
};
|
|
475
|
+
main().catch((error) => {
|
|
476
|
+
process.stderr.write(`rust-policy: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
477
|
+
process.exitCode = 1;
|
|
478
|
+
});
|
|
479
|
+
//#endregion
|
|
480
|
+
|
|
481
|
+
//# sourceMappingURL=rust-policy-cli.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rust-policy-cli.cjs","names":["record","record","posix","join","checkGeneratedOutput","parse","readFile","readdir","stat","parse","readFile","realpath","checkGeneratedOutput","join","stringify","writeGeneratedFile","readFile"],"sources":["../src/rust-policy-ownership.ts","../src/rust-workspace-members.ts","../src/rust-policy.ts","../src/rust-policy-cli.ts"],"sourcesContent":["const marker = \"# stll-rust-policy-owned-v1: \";\nconst markerPrefix = \"# stll-rust-policy-owned-\";\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** Arrays are policy values; inline TOML tables expose individually owned leaves. */\nexport const policyLeaves = (\n table: Record<string, unknown>,\n prefix: string[] = [],\n): string[][] =>\n Object.entries(table)\n .sort(([left], [right]) => left.localeCompare(right))\n .flatMap(([key, value]) =>\n record(value)\n ? policyLeaves(value, [...prefix, key])\n : [[...prefix, key]],\n );\n\nconst inManagedScope = (file: string, path: string[]) => {\n if (file === \"rustfmt.toml\" || file === \"clippy.toml\")\n return path.length === 1;\n if (file === \".cargo/config.toml\")\n return path.length === 2 && path.at(0) === \"alias\";\n if (!file.endsWith(\"Cargo.toml\")) return false;\n const root = file === \"Cargo.toml\";\n if (root && path.at(0) === \"profile\")\n return (\n path.length === 3 && [\"release\", \"dev\", \"ci\"].includes(path.at(1) ?? \"\")\n );\n const lintPath = path.at(0) === \"workspace\" && root ? path.slice(1) : path;\n if (lintPath.at(0) !== \"lints\") return false;\n if (lintPath.length === 2) return lintPath.at(1) === \"workspace\";\n if (![\"rust\", \"rustdoc\", \"clippy\"].includes(lintPath.at(1) ?? \"\"))\n return false;\n return (\n lintPath.length === 3 ||\n (lintPath.length === 4 &&\n [\"level\", \"priority\"].includes(lintPath.at(3) ?? \"\"))\n );\n};\n\nconst validatePaths = (file: string, input: unknown) => {\n if (!Array.isArray(input)) throw new Error(\"invalid Rust ownership metadata\");\n const paths = input.map((entry: unknown) => {\n if (\n !Array.isArray(entry) ||\n entry.length === 0 ||\n !entry.every(\n (part: unknown) =>\n typeof part === \"string\" &&\n /^[A-Za-z0-9_-]+$/.test(part) &&\n ![\"__proto__\", \"constructor\", \"prototype\"].includes(part),\n )\n )\n throw new Error(\"invalid Rust ownership path\");\n const path = entry.map((part: unknown) => {\n if (typeof part !== \"string\") throw new Error(\"invalid ownership path\");\n return part;\n });\n if (!inManagedScope(file, path))\n throw new Error(`Rust ownership metadata escapes managed scope: ${file}`);\n return path;\n });\n const seen = new Set<string>();\n for (const path of paths) {\n const key = JSON.stringify(path);\n if (seen.has(key)) throw new Error(\"duplicate Rust ownership path\");\n seen.add(key);\n for (let length = 1; length < path.length; length++)\n if (\n paths.some(\n (other) =>\n JSON.stringify(other) === JSON.stringify(path.slice(0, length)),\n )\n )\n throw new Error(\"overlapping Rust ownership paths\");\n }\n return paths;\n};\n\nexport const ownershipHeader = (\n file: string,\n owned: Record<string, unknown>,\n) => {\n // Resolver is a project-owned setting, even when seeded by the template.\n const paths = policyLeaves(owned).filter(\n (path) => JSON.stringify(path) !== '[\"workspace\",\"resolver\"]',\n );\n validatePaths(file, paths);\n return `${marker}${JSON.stringify(paths)}\\n`;\n};\n\nconst removeLeaf = (table: Record<string, unknown>, path: string[]) => {\n const key = path.at(0);\n if (key === undefined || !Object.hasOwn(table, key)) return;\n const value = table[key];\n if (path.length === 1) {\n if (record(value))\n throw new Error(\n \"Rust ownership leaf became a table; resolve ownership explicitly\",\n );\n Reflect.deleteProperty(table, key);\n return;\n }\n if (!record(value))\n throw new Error(\n \"Rust ownership table became a value; resolve ownership explicitly\",\n );\n removeLeaf(value, path.slice(1));\n if (Object.keys(value).length === 0) Reflect.deleteProperty(table, key);\n};\n\nconst previousPolicyPaths = (file: string, current: string | undefined) => {\n const declarations: string[] = [];\n // Metadata belongs to the leading comment block, never a TOML string value.\n for (const line of (current ?? \"\").split(\"\\n\")) {\n if (line.trim() !== \"\" && !line.startsWith(\"#\")) break;\n if (line.startsWith(markerPrefix)) declarations.push(line);\n }\n if (declarations.length === 0) return undefined;\n const declaration = declarations.at(0);\n if (\n declarations.length !== 1 ||\n declaration === undefined ||\n !declaration.startsWith(marker)\n )\n throw new Error(\"invalid Rust ownership metadata version or count\");\n const paths = validatePaths(\n file,\n JSON.parse(declaration.slice(marker.length)),\n );\n return paths;\n};\n\nexport const removePreviousPolicy = (\n file: string,\n current: string | undefined,\n document: Record<string, unknown>,\n) => {\n for (const path of previousPolicyPaths(file, current) ?? [])\n removeLeaf(document, path);\n};\n\nexport const removePreviousMemberPolicy = (\n file: string,\n current: string,\n document: Record<string, unknown>,\n) => {\n const paths = previousPolicyPaths(file, current);\n if (paths === undefined) {\n const lints = document[\"lints\"];\n if (record(lints) && Object.hasOwn(lints, \"workspace\"))\n throw new Error(\n `retired member must retain its generated inheritance ownership: ${file}`,\n );\n return \"unmanaged\";\n }\n if (paths.some((path) => JSON.stringify(path) !== '[\"lints\",\"workspace\"]'))\n throw new Error(\n `retired member must retain its generated inheritance ownership: ${file}`,\n );\n for (const path of paths) removeLeaf(document, path);\n return \"owned\";\n};\n\nconst memberMarker = \"# stll-rust-policy-members-v1: \";\nconst memberPrefix = \"# stll-rust-policy-members-\";\nconst memberPaths = (input: unknown) => {\n if (!Array.isArray(input))\n throw new Error(\"invalid Rust member ownership index\");\n const paths = input.map((value: unknown) => {\n if (\n typeof value !== \"string\" ||\n value === \"Cargo.toml\" ||\n !value.endsWith(\"/Cargo.toml\") ||\n value.includes(\"\\\\\") ||\n /\\p{Cc}/u.test(value) ||\n /^[A-Za-z]:/u.test(value) ||\n value\n .split(\"/\")\n .some((part) => part === \".\" || part === \"..\" || part === \"\")\n )\n throw new Error(\n \"Rust member ownership paths must be canonical repository Cargo.toml paths\",\n );\n return value;\n });\n if (new Set(paths).size !== paths.length)\n throw new Error(\"duplicate Rust member ownership path\");\n return paths;\n};\n\nexport const previousMemberPaths = (source: string) => {\n const declarations: string[] = [];\n for (const line of source.split(\"\\n\")) {\n if (line.trim() !== \"\" && !line.startsWith(\"#\")) break;\n if (line.startsWith(memberPrefix)) declarations.push(line);\n }\n if (declarations.length === 0) return [];\n const declaration = declarations.at(0);\n if (\n declarations.length !== 1 ||\n declaration === undefined ||\n !declaration.startsWith(memberMarker)\n )\n throw new Error(\"invalid Rust member ownership index version or count\");\n return memberPaths(JSON.parse(declaration.slice(memberMarker.length)));\n};\n\nexport const memberOwnershipHeader = (members: string[]) =>\n `${memberMarker}${JSON.stringify(memberPaths(members.filter((file) => file !== \"Cargo.toml\")))}\\n`;\n","import { readdir, readFile, stat } from \"node:fs/promises\";\nimport { join, posix } from \"node:path\";\nimport picomatch from \"picomatch\";\nimport { parse } from \"smol-toml\";\n\nimport { checkGeneratedOutput } from \"./generated-file\";\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\nconst patterns = (value: unknown) => {\n if (value === undefined) return [];\n if (!Array.isArray(value))\n throw new Error(\"workspace members/exclude must be arrays\");\n return value.map((entry: unknown) => {\n if (\n typeof entry !== \"string\" ||\n entry.length === 0 ||\n entry.startsWith(\"/\") ||\n entry.includes(\"\\\\\") ||\n entry.split(\"/\").includes(\"..\")\n )\n throw new Error(\"workspace patterns must remain inside the repository\");\n return posix.normalize(entry);\n });\n};\nconst checkRealAncestors = async (root: string, directory: string) => {\n let parent = root;\n for (const component of directory\n .split(\"/\")\n .filter((part) => part !== \".\" && part !== \"\")) {\n parent = join(parent, component);\n await checkGeneratedOutput(join(parent, \".stll-path-check\"));\n }\n};\nconst safeManifest = async (root: string, directory: string) => {\n await checkRealAncestors(root, directory);\n const path = join(root, directory, \"Cargo.toml\");\n const output = await checkGeneratedOutput(path);\n return output === undefined ? undefined : parse(await readFile(path, \"utf8\"));\n};\n\n/** Keep globstar states alive while consuming only actual directory components. */\nconst memberPrefixMatcher = (pattern: string) => {\n const segments = pattern.split(\"/\");\n // Cross-separator groups cannot be matched one component at a time. Retain\n // conservative feasibility from that group onward, after matching its prefix.\n const uncertain = segments.findIndex((segment) => {\n const closing: string[] = [];\n for (const character of segment) {\n if (closing.at(-1) === \"]\") {\n if (character === \"]\") closing.pop();\n continue;\n }\n if (character === \"[\") closing.push(\"]\");\n else if (character === \"{\") closing.push(\"}\");\n else if (character === \"(\") closing.push(\")\");\n else if (character === closing.at(-1)) closing.pop();\n }\n return closing.length > 0;\n });\n const matchers = segments.map((segment) => picomatch(segment, { dot: true }));\n return (directory: string) => {\n if (pattern.startsWith(\"!\") && !pattern.startsWith(\"!(\")) return true;\n let states = new Set([0]);\n const expand = () => {\n for (const state of states)\n if (segments[state] === \"**\") states.add(state + 1);\n };\n expand();\n for (const component of directory === \".\" ? [] : directory.split(\"/\")) {\n if (uncertain >= 0 && states.has(uncertain)) return true;\n const next = new Set<number>();\n for (const state of states) {\n if (segments[state] === \"**\") next.add(state);\n else if (matchers[state]?.(component)) next.add(state + 1);\n }\n states = next;\n expand();\n }\n return states.size > 0;\n };\n};\n\n/** Expand only declared member subtrees, then follow in-tree path dependencies. */\nexport const rustWorkspaceMembers = async (\n root: string,\n manifest: Record<string, unknown>,\n) => {\n const workspace = manifest[\"workspace\"];\n if (!record(workspace))\n throw new Error(\"workspace kind requires a workspace manifest\");\n const declaredMembers = patterns(workspace[\"members\"]);\n const excludes = patterns(workspace[\"exclude\"]);\n const within = (directory: string, prefix: string) =>\n prefix === \".\" ||\n directory === prefix ||\n directory.startsWith(`${prefix}/`);\n // Cargo checks literal path prefixes here, including the original member\n // strings. A glob-expanded member does not override an exclusion prefix.\n const excluded = (directory: string) =>\n excludes.some((prefix) => within(directory, prefix)) &&\n !declaredMembers.some((prefix) => within(directory, prefix));\n const excludedSubtree = (directory: string) =>\n excluded(directory) &&\n !declaredMembers.some((member) => within(member, directory));\n const members = new Map<string, Record<string, unknown>>();\n if (record(manifest[\"package\"])) members.set(\".\", manifest);\n for (const pattern of declaredMembers) {\n const scan = picomatch.scan(pattern);\n if (!scan.isGlob) {\n if (excluded(pattern)) continue;\n const member = await safeManifest(root, pattern);\n if (member === undefined)\n throw new Error(`missing workspace member: ${pattern}`);\n members.set(pattern, member);\n continue;\n }\n // Mutated inside the recursive walk; an object keeps the final check honest.\n const outcome = { matches: 0, prunedExclusion: false };\n const canContainMember = memberPrefixMatcher(pattern);\n const maximumDepth = pattern.includes(\"**\")\n ? Infinity\n : pattern.split(\"/\").length;\n const walk = async (directory: string) => {\n const depth = directory === \".\" ? 0 : directory.split(\"/\").length;\n if (!canContainMember(directory)) return;\n if (excludedSubtree(directory)) {\n outcome.prunedExclusion = true;\n return;\n }\n if (picomatch.isMatch(directory, pattern, { dot: true })) {\n outcome.matches++;\n if (!excluded(directory)) {\n const member = await safeManifest(root, directory);\n if (member === undefined)\n throw new Error(`missing workspace member manifest: ${directory}`);\n members.set(directory, member);\n }\n }\n if (depth >= maximumDepth) return;\n // Validate ancestors before traversing a declared subtree.\n await checkRealAncestors(root, directory);\n for (const entry of await readdir(join(root, directory), {\n withFileTypes: true,\n })) {\n const child = posix.join(directory, entry.name);\n if (!canContainMember(child)) continue;\n if (excludedSubtree(child)) {\n outcome.prunedExclusion = true;\n continue;\n }\n if (entry.isSymbolicLink()) {\n // Follow metadata only: regular-file links cannot contain members.\n // Relevant dangling/cyclic links fail closed when stat throws.\n if ((await stat(join(root, child))).isDirectory())\n throw new Error(\"workspace members must use real directories\");\n continue;\n }\n if (entry.isDirectory()) await walk(child);\n }\n };\n await walk(scan.base || \".\");\n if (outcome.matches === 0 && !outcome.prunedExclusion)\n throw new Error(`workspace pattern matched no manifests: ${pattern}`);\n }\n const inherited = workspace[\"dependencies\"];\n // Map iteration includes newly added dependencies, so transitive members converge.\n for (const [directory, member] of members) {\n const owners = [member];\n const targets = member[\"target\"];\n if (record(targets))\n for (const target of Object.values(targets))\n if (record(target)) owners.push(target);\n for (const owner of owners)\n for (const key of [\n \"dependencies\",\n \"dev-dependencies\",\n \"build-dependencies\",\n ]) {\n const dependencies = owner[key];\n if (!record(dependencies)) continue;\n for (const [name, dependency] of Object.entries(dependencies)) {\n if (!record(dependency)) continue;\n const isInherited = dependency[\"workspace\"] === true;\n const resolved =\n isInherited && record(inherited) ? inherited[name] : dependency;\n if (!record(resolved) || typeof resolved[\"path\"] !== \"string\")\n continue;\n if (\n posix.isAbsolute(resolved[\"path\"]) ||\n resolved[\"path\"].includes(\"\\\\\")\n )\n throw new Error(\n \"path dependencies must use portable relative paths\",\n );\n const target = posix.normalize(\n posix.join(isInherited ? \".\" : directory, resolved[\"path\"]),\n );\n if (\n target === \"..\" ||\n target.startsWith(\"../\") ||\n excluded(target) ||\n members.has(target)\n )\n continue;\n const parsed = await safeManifest(root, target);\n if (parsed === undefined)\n throw new Error(`missing path dependency manifest: ${target}`);\n members.set(target, parsed);\n }\n }\n }\n return [...members.keys()]\n .sort()\n .map((directory) => posix.join(directory, \"Cargo.toml\"));\n};\n","import { readFile, realpath } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { parse, stringify } from \"smol-toml\";\n\nimport { checkGeneratedOutput, writeGeneratedFile } from \"./generated-file\";\nimport {\n memberOwnershipHeader,\n ownershipHeader,\n previousMemberPaths,\n removePreviousMemberPolicy,\n removePreviousPolicy,\n} from \"./rust-policy-ownership\";\nimport { rustWorkspaceMembers } from \"./rust-workspace-members\";\n\ndeclare const STLL_RUST_TEMPLATES: Record<string, string>;\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\nconst keys = (value: Record<string, unknown>, allowed: string[]) => {\n if (Object.keys(value).some((key) => !allowed.includes(key)))\n throw new Error(\"unknown Rust policy input field\");\n};\nexport const parseRustPolicy = (input: unknown) => {\n if (!record(input)) throw new Error(\"Rust policy input must be an object\");\n keys(input, [\"kind\", \"exceptions\"]);\n if (input[\"kind\"] !== \"single-crate\" && input[\"kind\"] !== \"workspace\")\n throw new Error(\"kind must be single-crate or workspace\");\n const exceptions = input[\"exceptions\"] ?? [];\n if (!Array.isArray(exceptions))\n throw new Error(\"exceptions must be an array\");\n const parsedExceptions = exceptions.map((entry: unknown) => {\n if (!record(entry)) throw new Error(\"exception must be an object\");\n keys(entry, [\"file\", \"path\", \"value\", \"reason\"]);\n if (\n typeof entry[\"file\"] !== \"string\" ||\n !Array.isArray(entry[\"path\"]) ||\n entry[\"path\"].length === 0 ||\n !entry[\"path\"].every(\n (part: unknown) => typeof part === \"string\" && part.length > 0,\n ) ||\n !(\"value\" in entry) ||\n typeof entry[\"reason\"] !== \"string\" ||\n entry[\"reason\"].trim().length === 0\n )\n throw new Error(\n \"exceptions require file, nonempty path, value and reason\",\n );\n const path = entry[\"path\"].map((part: unknown) => {\n if (typeof part !== \"string\") throw new Error(\"invalid exception path\");\n return part;\n });\n return { file: entry[\"file\"], path, value: entry[\"value\"] };\n });\n return { kind: input[\"kind\"], exceptions: parsedExceptions };\n};\nconst merge = (\n target: Record<string, unknown>,\n policy: Record<string, unknown>,\n) => {\n for (const [key, value] of Object.entries(policy)) {\n if (!record(value)) {\n target[key] = value;\n continue;\n }\n const existing = target[key];\n if (existing !== undefined && !record(existing))\n throw new Error(`policy table conflicts with value: ${key}`);\n const table = record(existing) ? existing : {};\n merge(table, value);\n target[key] = table;\n }\n};\nconst requirePolicyTable = (value: unknown): Record<string, unknown> => {\n if (!record(value))\n throw new Error(\"exception path must name an existing policy value\");\n return value;\n};\nconst template = async (name: string) => {\n const text =\n typeof STLL_RUST_TEMPLATES === \"undefined\"\n ? await readFile(\n new URL(`../../../rust/${name}`, import.meta.url),\n \"utf8\",\n )\n : STLL_RUST_TEMPLATES[name];\n if (text === undefined) throw new Error(`missing Rust template: ${name}`);\n return parse(text);\n};\nconst optionalText = async (path: string) => {\n try {\n return await readFile(path, \"utf8\");\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\")\n return undefined;\n throw error;\n }\n};\ntype GenerateRustPolicyOptions = {\n root: string;\n input: unknown;\n mode: \"write\" | \"check\";\n};\nexport const generateRustPolicy = async ({\n root,\n input,\n mode,\n}: GenerateRustPolicyOptions) => {\n const policy = parseRustPolicy(input);\n const repository = await realpath(root);\n await checkGeneratedOutput(join(repository, \"Cargo.toml\"));\n const rootSource = await readFile(join(repository, \"Cargo.toml\"), \"utf8\");\n const manifest = parse(rootSource);\n const previousMembers = previousMemberPaths(rootSource);\n const members =\n policy.kind === \"workspace\"\n ? await rustWorkspaceMembers(repository, manifest)\n : [];\n const cargoPolicy = await template(\n policy.kind === \"workspace\" ? \"cargo-workspace.toml\" : \"cargo-root.toml\",\n );\n const workspace = manifest[\"workspace\"];\n const generatedWorkspace = cargoPolicy[\"workspace\"];\n // Cargo's resolver belongs to the project; the template supplies a default.\n if (\n record(workspace) &&\n record(generatedWorkspace) &&\n workspace[\"resolver\"] !== undefined\n )\n generatedWorkspace[\"resolver\"] = workspace[\"resolver\"];\n const outputs = new Map<string, Record<string, unknown>>([\n [\"Cargo.toml\", cargoPolicy],\n [\".cargo/config.toml\", await template(\"cargo-config.toml\")],\n [\"rustfmt.toml\", await template(\"rustfmt.toml\")],\n [\"clippy.toml\", await template(\"clippy.toml\")],\n ]);\n for (const member of members) {\n if (member === \"Cargo.toml\") {\n merge(cargoPolicy, { lints: { workspace: true } });\n continue;\n }\n outputs.set(member, { lints: { workspace: true } });\n }\n const seen = new Set<string>();\n for (const exception of policy.exceptions) {\n const signature = JSON.stringify([exception.file, exception.path]);\n if (seen.has(signature)) throw new Error(\"duplicate Rust policy exception\");\n seen.add(signature);\n let table = outputs.get(exception.file);\n if (table === undefined)\n throw new Error(\"exception file is not a generated output\");\n if (\n exception.path.length === 2 &&\n exception.path.at(0) === \"lints\" &&\n exception.path.at(1) === \"workspace\"\n )\n throw new Error(\n \"workspace lint inheritance is structural and cannot be excepted\",\n );\n const last = exception.path.at(-1);\n for (const key of exception.path.slice(0, -1)) {\n if (!Object.hasOwn(table, key))\n throw new Error(\"exception path must name an existing policy value\");\n table = requirePolicyTable(table[key]);\n }\n if (\n last === undefined ||\n !Object.hasOwn(table, last) ||\n record(table[last])\n )\n throw new Error(\"exception must replace a policy leaf\");\n const previous = table[last];\n if (\n typeof previous !== typeof exception.value ||\n Array.isArray(previous) !== Array.isArray(exception.value) ||\n exception.value === null\n )\n throw new Error(\"exception must preserve the policy value type\");\n table[last] = exception.value;\n }\n const plans = [];\n const retired = previousMembers.filter((file) => !outputs.has(file));\n for (const file of [...outputs.keys(), ...retired]) {\n const owned = outputs.get(file);\n const destination = join(repository, file);\n let parent = repository;\n for (const segment of file.split(\"/\").slice(0, -1)) {\n parent = join(parent, segment);\n await checkGeneratedOutput(join(parent, \".stll-path-check\"));\n }\n const stat = await checkGeneratedOutput(destination);\n const current = await optionalText(destination);\n if (owned === undefined && current === undefined) continue;\n if (file.endsWith(\"Cargo.toml\") && current === undefined)\n throw new Error(`missing manifest: ${file}`);\n const document = current === undefined ? {} : parse(current);\n if (file.endsWith(\"Cargo.toml\")) {\n const lints = document[\"lints\"];\n const member = policy.kind === \"workspace\" && members.includes(file);\n if (\n member &&\n record(lints) &&\n Object.keys(lints).some((key) => key !== \"workspace\")\n )\n throw new Error(\n `remove local lint tables before workspace inheritance: ${file}`,\n );\n if (\n file === \"Cargo.toml\" &&\n policy.kind === \"single-crate\" &&\n record(lints) &&\n lints[\"workspace\"] === true\n )\n throw new Error(\"single-crate lints cannot inherit workspace policy\");\n if (\n file === \"Cargo.toml\" &&\n policy.kind === \"workspace\" &&\n !record(document[\"workspace\"])\n )\n throw new Error(\"workspace kind requires a workspace manifest\");\n if (\n file === \"Cargo.toml\" &&\n policy.kind === \"single-crate\" &&\n \"workspace\" in document\n )\n throw new Error(\"use workspace kind for workspace manifests\");\n }\n if (owned === undefined) {\n if (current === undefined)\n throw new Error(\"retired member source missing\");\n if (removePreviousMemberPolicy(file, current, document) === \"unmanaged\")\n continue;\n } else {\n removePreviousPolicy(file, current, document);\n merge(document, owned);\n }\n const indexHeader =\n file === \"Cargo.toml\" ? memberOwnershipHeader(members) : \"\";\n const text = `# Generated by stll-rust-policy; edit policy input for exceptions.\\n${ownershipHeader(file, owned ?? {})}${indexHeader}${stringify(document)}`;\n plans.push({\n file,\n destination,\n text,\n current,\n mode: stat === undefined ? 0o644 : stat.mode & 0o777,\n });\n }\n const drift = plans\n .filter(({ text, current }) => text !== current)\n .map(({ file }) => file);\n if (mode === \"check\") return drift;\n const rootPlan = plans.find(({ file }) => file === \"Cargo.toml\");\n if (rootPlan === undefined) throw new Error(\"root ownership plan missing\");\n // Write ahead every cleanup obligation, including pending new enrollments.\n const union = [...new Set([...previousMembers, ...members])].sort();\n const journalText = rootPlan.text.replace(\n memberOwnershipHeader(members),\n memberOwnershipHeader(union),\n );\n if (journalText !== rootPlan.current)\n await writeGeneratedFile({ ...rootPlan, text: journalText });\n for (const plan of plans.filter(({ file }) => file !== \"Cargo.toml\"))\n if (plan.text !== plan.current) await writeGeneratedFile(plan);\n // Retire obligations only after every affected member has been written.\n if (rootPlan.text !== journalText) await writeGeneratedFile(rootPlan);\n return drift;\n};\n","#!/usr/bin/env node\nimport { readFile } from \"node:fs/promises\";\n\nimport { generateRustPolicy } from \"./rust-policy\";\n\nconst usage =\n \"Usage: stll-rust-policy [--check] [--config <path>]\\nRun from the repository root; default input: stll-rust-policy.json\";\nconst main = async () => {\n const args = process.argv.slice(2);\n if (args.length === 1 && args.at(0) === \"--help\") {\n process.stdout.write(`${usage}\\n`);\n return;\n }\n let mode: \"write\" | \"check\" = \"write\";\n let config = \"stll-rust-policy.json\";\n const seen = new Set<string>();\n for (let index = 0; index < args.length; index++) {\n const arg = args.at(index);\n if (arg === undefined || seen.has(arg)) throw new Error(usage);\n seen.add(arg);\n if (arg === \"--check\") {\n mode = \"check\";\n continue;\n }\n if (arg !== \"--config\") throw new Error(usage);\n const path = args.at(++index);\n if (path === undefined || path.startsWith(\"--\")) throw new Error(usage);\n config = path;\n }\n const drift = await generateRustPolicy({\n root: process.cwd(),\n input: JSON.parse(await readFile(config, \"utf8\")),\n mode,\n });\n if (mode === \"check\" && drift.length > 0)\n throw new Error(\n `Rust policy drift: ${drift.join(\", \")}; run stll-rust-policy`,\n );\n};\nmain().catch((error: unknown) => {\n process.stderr.write(\n `rust-policy: ${error instanceof Error ? error.message : String(error)}\\n`,\n );\n process.exitCode = 1;\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|