1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.validatePackageURL = exports.validateGraph = void 0;
|
4 | const graphlib = require("../graphlib");
|
5 | const packageurl_js_1 = require("packageurl-js");
|
6 | const errors_1 = require("./errors");
|
7 | const reGolangPseudoVersion = /(v\d+\.\d+\.\d+)-(.*?)(\d{14})-([0-9a-f]{12})/;
|
8 | const reGolangExactVersion = /^(.*?)(\+incompatible)?$/;
|
9 | function assert(condition, msg) {
|
10 | if (!condition) {
|
11 | throw new errors_1.ValidationError(msg);
|
12 | }
|
13 | }
|
14 | function validateGraph(graph, rootNodeId, pkgs, pkgNodes) {
|
15 | assert((graph.predecessors(rootNodeId) || []).length === 0, `"${rootNodeId}" is not really the root`);
|
16 | const reachableFromRoot = graphlib.alg.postorder(graph, [rootNodeId]);
|
17 | const nodeIds = graph.nodes();
|
18 | assert(JSON.stringify(nodeIds.sort()) === JSON.stringify(reachableFromRoot.sort()), 'not all graph nodes are reachable from root');
|
19 | const pkgIds = Object.keys(pkgs);
|
20 | const pkgsWithoutInstances = pkgIds.filter((pkgId) => !pkgNodes[pkgId] || pkgNodes[pkgId].size === 0);
|
21 | assert(pkgsWithoutInstances.length === 0, 'not all pkgs have instance nodes');
|
22 | for (const pkgId in pkgs) {
|
23 | try {
|
24 | validatePackageURL(pkgs[pkgId]);
|
25 | }
|
26 | catch (e) {
|
27 | throw new errors_1.ValidationError(`invalid pkg ${pkgId}: ${e}`);
|
28 | }
|
29 | }
|
30 | }
|
31 | exports.validateGraph = validateGraph;
|
32 | function validatePackageURL(pkg) {
|
33 | var _a;
|
34 | if (!pkg.purl) {
|
35 | return;
|
36 | }
|
37 | try {
|
38 | const purl = packageurl_js_1.PackageURL.fromString(pkg.purl);
|
39 |
|
40 | switch (purl.type) {
|
41 |
|
42 |
|
43 | case 'maven':
|
44 | assert(pkg.name === purl.namespace + ':' + purl.name, `name and packageURL name do not match`);
|
45 | break;
|
46 |
|
47 |
|
48 |
|
49 | case 'cocoapods':
|
50 | assert(pkg.name ===
|
51 | (purl.subpath ? `${purl.name}/${purl.subpath}` : purl.name), `name and packageURL name do not match`);
|
52 | break;
|
53 | case 'golang': {
|
54 | let expected = purl.namespace
|
55 | ? `${purl.namespace}/${purl.name}`
|
56 | : purl.name;
|
57 | if (purl.subpath)
|
58 | expected += `/${purl.subpath}`;
|
59 | assert(pkg.name === expected, `name and packageURL name do not match`);
|
60 | break;
|
61 | }
|
62 | case 'composer':
|
63 | case 'npm':
|
64 | case 'swift':
|
65 | assert(pkg.name ===
|
66 | (purl.namespace ? `${purl.namespace}/${purl.name}` : purl.name), `name and packageURL name do not match`);
|
67 | break;
|
68 |
|
69 |
|
70 |
|
71 |
|
72 | case 'deb': {
|
73 | const pkgName = pkg.name.split('/').pop();
|
74 | assert(pkgName === purl.name, 'name and packageURL name do not match');
|
75 | if (((_a = purl.qualifiers) === null || _a === void 0 ? void 0 : _a['upstream']) && pkg.name.includes('/')) {
|
76 | const pkgSrc = pkg.name.split('/')[0];
|
77 | const pkgUpstream = purl.qualifiers['upstream'].split('@')[0];
|
78 | assert(pkgSrc === pkgUpstream, 'source and packageURL source do not match');
|
79 | }
|
80 | break;
|
81 | }
|
82 | default:
|
83 | assert(pkg.name === purl.name, `name and packageURL name do not match`);
|
84 | }
|
85 |
|
86 | switch (purl.type) {
|
87 |
|
88 |
|
89 |
|
90 | case 'golang': {
|
91 | let version = purl.version;
|
92 | if (purl.version) {
|
93 | const maybePseudoVersion = reGolangPseudoVersion.exec(purl.version);
|
94 | const maybeExactVersion = reGolangExactVersion.exec(purl.version);
|
95 | if (maybePseudoVersion) {
|
96 | version = `#${maybePseudoVersion[4]}`;
|
97 | }
|
98 | else if (maybeExactVersion) {
|
99 | version = maybeExactVersion[1].replace(/^v/, '');
|
100 | }
|
101 | }
|
102 | assert(pkg.version === version, `version and packageURL version do not match. want ${pkg.version} have: ${version}`);
|
103 | break;
|
104 | }
|
105 | default:
|
106 | assert(pkg.version === purl.version, `version and packageURL version do not match`);
|
107 | }
|
108 | }
|
109 | catch (e) {
|
110 | throw new errors_1.ValidationError(`packageURL validation failed: ${e}`);
|
111 | }
|
112 | }
|
113 | exports.validatePackageURL = validatePackageURL;
|
114 |
|
\ | No newline at end of file |