snyk-gradle-plugin
Version:
Snyk CLI Gradle plugin
108 lines • 4.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildGraph = void 0;
const dep_graph_1 = require("@snyk/dep-graph");
const yocto_queue_1 = require("@common.js/yocto-queue");
const coordinate_1 = require("./coordinate");
function precomputeChildrenMap(gradleGraph) {
const childrenMap = new Map();
for (const id of Object.keys(gradleGraph)) {
const node = gradleGraph[id];
if (node === null || node === void 0 ? void 0 : node.parentIds) {
for (const parentId of node.parentIds) {
if (!childrenMap.has(parentId)) {
childrenMap.set(parentId, []);
}
childrenMap.get(parentId).push(id);
}
}
}
return childrenMap;
}
function findChildren(parentId, ancestry, childrenMap) {
const childrenIds = childrenMap.get(parentId) || [];
return childrenIds.map((id) => ({ id, ancestry, parentId }));
}
async function buildGraph(gradleGraph, rootPkgName, projectVersion, verbose, sha1Map) {
const pkgManager = { name: 'gradle' };
const isEmptyGraph = !gradleGraph || Object.keys(gradleGraph).length === 0;
const depGraphBuilder = new dep_graph_1.DepGraphBuilder(pkgManager, {
name: rootPkgName,
version: projectVersion || '0.0.0',
});
if (isEmptyGraph) {
return depGraphBuilder.build();
}
const childrenMap = precomputeChildrenMap(gradleGraph);
const visitedMap = {};
const queue = new yocto_queue_1.default();
findChildren('root-node', new Set(), childrenMap).forEach((item) => queue.enqueue(item));
// breadth first search
while (queue.size > 0) {
const item = queue.dequeue();
if (!item)
continue;
let { id, parentId } = item;
const { ancestry } = item;
// take a copy as id maybe mutated below and we need this id when finding childing in GradleGraph
const gradleGraphId = `${id}`;
const node = gradleGraph[id];
if (!node)
continue;
let { name = 'unknown', version = 'unknown' } = node;
let pkgIdProvenance = undefined;
if (sha1Map) {
if (sha1Map[id]) {
id = sha1Map[id];
const coord = (0, coordinate_1.parseCoordinate)(id);
const newName = `${coord.groupId}:${coord.artifactId}`;
const newVersion = coord.version;
if (name !== newName || version !== newVersion) {
pkgIdProvenance = `${name}@${version}`; // record pkg id provenance if re coordinated
name = newName;
version = newVersion;
}
}
if (sha1Map[parentId]) {
parentId = sha1Map[parentId];
}
}
const visited = visitedMap[id];
if (visited) {
if (!verbose) {
const prunedId = id + ':pruned';
depGraphBuilder.addPkgNode({ name, version }, prunedId, createNodeInfo(pkgIdProvenance, 'true'));
depGraphBuilder.connectDep(parentId, prunedId);
continue; // don't queue any more children
}
if (ancestry.has(id)) {
const prunedId = id + ':pruned';
depGraphBuilder.addPkgNode(visited, prunedId, createNodeInfo(pkgIdProvenance, 'cyclic'));
depGraphBuilder.connectDep(parentId, prunedId);
continue; // don't queue any more children
}
// Node already exists in dep graph builder
// use visited node when omitted dependencies found (verbose)
depGraphBuilder.connectDep(parentId, id);
}
else {
depGraphBuilder.addPkgNode({ name, version }, id, createNodeInfo(pkgIdProvenance));
depGraphBuilder.connectDep(parentId, id);
visitedMap[id] = { name, version };
}
// Remember to push updated ancestry here
const newAncestry = new Set(ancestry).add(id);
findChildren(gradleGraphId, newAncestry, childrenMap).forEach((item) => queue.enqueue(item));
}
return depGraphBuilder.build();
}
exports.buildGraph = buildGraph;
function createNodeInfo(pkgIdProvenance, pruned) {
const labels = {};
if (pruned)
labels.pruned = pruned;
if (pkgIdProvenance)
labels.pkgIdProvenance = pkgIdProvenance;
return Object.keys(labels).length ? { labels } : undefined;
}
//# sourceMappingURL=graph.js.map