snyk-go-plugin
Advanced tools
Comparing version 1.15.0 to 1.16.0
@@ -0,1 +1,2 @@ | ||
import { DepGraph } from '@snyk/dep-graph'; | ||
export interface DepDict { | ||
@@ -22,6 +23,15 @@ [name: string]: DepTree; | ||
}; | ||
package: DepTree; | ||
dependencyGraph: DepGraph | undefined; | ||
package?: undefined; | ||
} | { | ||
plugin: { | ||
name: string; | ||
runtime: string | undefined; | ||
targetFile: any; | ||
}; | ||
package: DepTree | undefined; | ||
dependencyGraph?: undefined; | ||
}>; | ||
export declare function buildDepTreeFromImportsAndModules(root?: string, targetFile?: string): Promise<DepTree>; | ||
export declare function buildDepGraphFromImportsAndModules(root?: string, targetFile?: string): Promise<DepGraph>; | ||
export declare function jsonParse(s: string): any; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.jsonParse = exports.buildDepTreeFromImportsAndModules = exports.inspect = void 0; | ||
exports.jsonParse = exports.buildDepGraphFromImportsAndModules = exports.inspect = void 0; | ||
const fs = require("fs"); | ||
const path = require("path"); | ||
const graphlib = require("@snyk/graphlib"); | ||
const tmp = require("tmp"); | ||
const debugLib = require("debug"); | ||
const graphlib = require("@snyk/graphlib"); | ||
const dep_graph_1 = require("@snyk/dep-graph"); | ||
const subProcess = require("./sub-process"); | ||
@@ -20,6 +21,19 @@ const custom_error_1 = require("./errors/custom-error"); | ||
]); | ||
return { | ||
plugin: result[0], | ||
package: result[1], | ||
}; | ||
const hasDepGraph = result[1].dependencyGraph && !result[1].dependencyTree; | ||
const hasDepTree = !result[1].dependencyGraph && result[1].dependencyTree; | ||
//TODO @boost: get rid of the rest of depTree and fully convert this plugin to use depGraph | ||
if (hasDepGraph) { | ||
return { | ||
plugin: result[0], | ||
dependencyGraph: result[1].dependencyGraph | ||
}; | ||
} | ||
else if (hasDepTree) { | ||
return { | ||
plugin: result[0], | ||
package: result[1].dependencyTree | ||
}; | ||
} | ||
//TODO @boost: remove me | ||
throw new Error('Failed to scan this go project.'); | ||
} | ||
@@ -90,3 +104,3 @@ exports.inspect = inspect; | ||
if (packageManager === 'gomodules') { | ||
return buildDepTreeFromImportsAndModules(root, targetFile); | ||
return { dependencyGraph: await buildDepGraphFromImportsAndModules(root, targetFile) }; | ||
} | ||
@@ -133,3 +147,3 @@ try { | ||
debug('done building dep-tree', { rootPkgName: pkgsTree.name }); | ||
return pkgsTree; | ||
return { dependencyTree: pkgsTree }; | ||
} | ||
@@ -285,10 +299,10 @@ catch (error) { | ||
} | ||
// TODO(kyegupov): move to a separate file | ||
async function buildDepTreeFromImportsAndModules(root = '.', targetFile = 'go.mod') { | ||
async function buildDepGraphFromImportsAndModules(root = '.', targetFile = 'go.mod') { | ||
// TODO(BST-657): parse go.mod file to obtain root module name and go version | ||
const depTree = { | ||
name: path.basename(root), | ||
version: '0.0.0', | ||
packageFormatVersion: 'golang:0.0.1', | ||
}; | ||
const projectName = path.basename(root); // The correct name should come from the `go list` command | ||
const projectVersion = '0.0.0'; // TODO(BST-657): try `git describe`? | ||
let depGraphBuilder = new dep_graph_1.DepGraphBuilder({ name: 'gomodules' }, { | ||
name: projectName, | ||
version: projectVersion, | ||
}); | ||
let goDepsOutput; | ||
@@ -305,3 +319,3 @@ try { | ||
if (goDepsOutput.includes('matched no packages')) { | ||
return depTree; | ||
return depGraphBuilder.build(); | ||
} | ||
@@ -318,10 +332,15 @@ const goDepsString = `[${goDepsOutput.replace(/}\r?\n{/g, '},{')}]`; | ||
if (localPackageWithMainModule && localPackageWithMainModule.Module.Path) { | ||
depTree.name = localPackageWithMainModule.Module.Path; | ||
depGraphBuilder = new dep_graph_1.DepGraphBuilder({ name: 'gomodules' }, { | ||
name: localPackageWithMainModule.Module.Path, | ||
version: projectVersion, | ||
}); | ||
} | ||
const topLevelDeps = extractAllImports(localPackages); | ||
buildTree(depTree, topLevelDeps, packagesByName); | ||
return depTree; | ||
const childrenChain = new Map(); | ||
const ancestorsChain = new Map(); | ||
buildGraph(depGraphBuilder, topLevelDeps, packagesByName, 'root-node', childrenChain, ancestorsChain); | ||
return depGraphBuilder.build(); | ||
} | ||
exports.buildDepTreeFromImportsAndModules = buildDepTreeFromImportsAndModules; | ||
function buildTree(depTreeNode, depPackages, packagesByName) { | ||
exports.buildDepGraphFromImportsAndModules = buildDepGraphFromImportsAndModules; | ||
function buildGraph(depGraphBuilder, depPackages, packagesByName, currentParent, childrenChain, ancestorsChain) { | ||
const depPackagesLen = depPackages.length; | ||
@@ -339,7 +358,8 @@ for (let i = depPackagesLen - 1; i >= 0; i--) { | ||
} | ||
else { | ||
const pkg = packagesByName[packageImport]; | ||
if (pkg.Module && pkg.Module.Version) { | ||
version = snyk_go_parser_1.toSnykVersion(snyk_go_parser_1.parseVersion(pkg.Module.Version)); | ||
} | ||
const pkg = packagesByName[packageImport]; | ||
if (pkg.Module && pkg.Module.Version) { | ||
// get hash (prefixed with #) or version (with v prefix removed) | ||
version = snyk_go_parser_1.toSnykVersion(snyk_go_parser_1.parseVersion(pkg.Module.Version)); | ||
} | ||
if (currentParent && packageImport) { | ||
const newNode = { | ||
@@ -349,8 +369,16 @@ name: packageImport, | ||
}; | ||
if (!depTreeNode.dependencies) { | ||
depTreeNode.dependencies = {}; | ||
const currentChildren = childrenChain.get(currentParent) || []; | ||
const currentAncestors = ancestorsChain.get(currentParent) || []; | ||
const isAncestorOrChild = currentChildren.includes(packageImport) || currentAncestors.includes(packageImport); | ||
//@TODO boost: breaking cycles, re-work once dep-graph lib can handle cycles | ||
if (packageImport === currentParent || isAncestorOrChild) { | ||
continue; | ||
} | ||
depTreeNode.dependencies[packageImport] = newNode; | ||
if (packagesByName[packageImport].Imports) { | ||
buildTree(newNode, packagesByName[packageImport].Imports, packagesByName); | ||
depGraphBuilder.addPkgNode(newNode, packageImport); | ||
depGraphBuilder.connectDep(currentParent, packageImport); | ||
childrenChain.set(currentParent, [...currentChildren, packageImport]); | ||
ancestorsChain.set(packageImport, [...currentAncestors, currentParent]); | ||
const transitives = packagesByName[packageImport].Imports || []; | ||
if (transitives.length > 0) { | ||
buildGraph(depGraphBuilder, transitives, packagesByName, packageImport, childrenChain, ancestorsChain); | ||
} | ||
@@ -357,0 +385,0 @@ } |
110
lib/index.ts
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
import * as graphlib from '@snyk/graphlib'; | ||
import * as tmp from 'tmp'; | ||
import debugLib = require('debug'); | ||
import * as graphlib from '@snyk/graphlib'; | ||
import { DepGraphBuilder, DepGraph } from '@snyk/dep-graph'; | ||
@@ -48,6 +49,21 @@ import * as subProcess from './sub-process'; | ||
]); | ||
return { | ||
plugin: result[0], | ||
package: result[1], | ||
}; | ||
const hasDepGraph = result[1].dependencyGraph && !result[1].dependencyTree; | ||
const hasDepTree = !result[1].dependencyGraph && result[1].dependencyTree; | ||
//TODO @boost: get rid of the rest of depTree and fully convert this plugin to use depGraph | ||
if(hasDepGraph) { | ||
return { | ||
plugin: result[0], | ||
dependencyGraph: result[1].dependencyGraph | ||
} | ||
} else if(hasDepTree) { | ||
return { | ||
plugin: result[0], | ||
package: result[1].dependencyTree | ||
} | ||
} | ||
//TODO @boost: remove me | ||
throw new Error('Failed to scan this go project.'); | ||
} | ||
@@ -132,3 +148,3 @@ | ||
if (packageManager === 'gomodules') { | ||
return buildDepTreeFromImportsAndModules(root, targetFile); | ||
return { dependencyGraph: await buildDepGraphFromImportsAndModules(root, targetFile)}; | ||
} | ||
@@ -192,3 +208,3 @@ | ||
return pkgsTree; | ||
return { dependencyTree: pkgsTree }; | ||
} catch (error) { | ||
@@ -456,18 +472,18 @@ if (tempDirObj) { | ||
// TODO(kyegupov): move to a separate file | ||
export async function buildDepTreeFromImportsAndModules(root: string = '.', targetFile: string = 'go.mod') { | ||
export async function buildDepGraphFromImportsAndModules(root: string = '.', targetFile: string = 'go.mod'): Promise<DepGraph> { | ||
// TODO(BST-657): parse go.mod file to obtain root module name and go version | ||
const projectName = path.basename(root); // The correct name should come from the `go list` command | ||
const projectVersion = '0.0.0'; // TODO(BST-657): try `git describe`? | ||
const depTree: DepTree = { | ||
name: path.basename(root), // The correct name should come from the `go list` command | ||
version: '0.0.0', // TODO(BST-657): try `git describe`? | ||
packageFormatVersion: 'golang:0.0.1', | ||
}; | ||
let depGraphBuilder = new DepGraphBuilder({ name: 'gomodules' }, { | ||
name: projectName, | ||
version: projectVersion, | ||
}); | ||
let goDepsOutput: string; | ||
try { | ||
const goModAbsolutPath = path.resolve(root, path.dirname(targetFile)); | ||
goDepsOutput = await subProcess.execute('go list', ['-json', '-deps', './...'], { cwd: goModAbsolutPath } ); | ||
} catch (err) { | ||
@@ -480,4 +496,5 @@ const userError = new CustomError(err); | ||
if (goDepsOutput.includes('matched no packages')) { | ||
return depTree; | ||
return depGraphBuilder.build(); | ||
} | ||
const goDepsString = `[${goDepsOutput.replace(/}\r?\n{/g, '},{')}]`; | ||
@@ -494,16 +511,23 @@ const goDeps: GoPackage[] = JSON.parse(goDepsString); | ||
if (localPackageWithMainModule && localPackageWithMainModule!.Module!.Path) { | ||
depTree.name = localPackageWithMainModule!.Module!.Path; | ||
depGraphBuilder = new DepGraphBuilder({ name: 'gomodules' }, { | ||
name: localPackageWithMainModule!.Module!.Path, | ||
version: projectVersion, | ||
}); | ||
} | ||
const topLevelDeps = extractAllImports(localPackages); | ||
const childrenChain = new Map(); | ||
const ancestorsChain = new Map(); | ||
const topLevelDeps = extractAllImports(localPackages); | ||
buildTree(depTree, topLevelDeps, packagesByName); | ||
return depTree; | ||
buildGraph(depGraphBuilder, topLevelDeps, packagesByName, 'root-node', childrenChain, ancestorsChain); | ||
return depGraphBuilder.build(); | ||
} | ||
function buildTree( | ||
depTreeNode: DepTree, | ||
function buildGraph(depGraphBuilder: DepGraphBuilder, | ||
depPackages: string[], | ||
packagesByName: GoPackagesByName, | ||
) { | ||
packagesByName: GoPackagesByName, currentParent: string, childrenChain: Map<string, Array<string>>, ancestorsChain: Map<string, Array<string>>) { | ||
const depPackagesLen = depPackages.length; | ||
for (let i = depPackagesLen - 1; i >= 0; i--) { | ||
@@ -518,7 +542,12 @@ const packageImport = depPackages[i]; | ||
continue; | ||
} else { | ||
const pkg = packagesByName[packageImport]!; | ||
if (pkg.Module && pkg.Module.Version) { | ||
version = toSnykVersion(parseVersion(pkg.Module.Version)); | ||
} | ||
} | ||
const pkg = packagesByName[packageImport]!; | ||
if (pkg.Module && pkg.Module.Version) { | ||
// get hash (prefixed with #) or version (with v prefix removed) | ||
version = toSnykVersion(parseVersion(pkg.Module.Version)); | ||
} | ||
if(currentParent && packageImport) { | ||
const newNode = { | ||
@@ -528,8 +557,21 @@ name: packageImport, | ||
}; | ||
if (!depTreeNode.dependencies) { | ||
depTreeNode.dependencies = {}; | ||
const currentChildren = childrenChain.get(currentParent) || []; | ||
const currentAncestors = ancestorsChain.get(currentParent) || []; | ||
const isAncestorOrChild = currentChildren.includes(packageImport) || currentAncestors.includes(packageImport); | ||
//@TODO boost: breaking cycles, re-work once dep-graph lib can handle cycles | ||
if(packageImport === currentParent || isAncestorOrChild) { | ||
continue; | ||
} | ||
depTreeNode.dependencies![packageImport] = newNode; | ||
if (packagesByName[packageImport].Imports) { | ||
buildTree(newNode, packagesByName[packageImport].Imports!, packagesByName); | ||
depGraphBuilder.addPkgNode(newNode, packageImport); | ||
depGraphBuilder.connectDep(currentParent, packageImport); | ||
childrenChain.set(currentParent, [...currentChildren, packageImport]); | ||
ancestorsChain.set(packageImport, [...currentAncestors, currentParent]); | ||
const transitives = packagesByName[packageImport].Imports! || []; | ||
if (transitives.length > 0) { | ||
buildGraph(depGraphBuilder, transitives, packagesByName, packageImport, childrenChain, ancestorsChain); | ||
} | ||
@@ -536,0 +578,0 @@ } |
@@ -27,2 +27,3 @@ { | ||
"dependencies": { | ||
"@snyk/dep-graph": "1.19.3", | ||
"@snyk/graphlib": "2.1.9-patch", | ||
@@ -44,3 +45,3 @@ "debug": "^4.1.1", | ||
}, | ||
"version": "1.15.0" | ||
"version": "1.16.0" | ||
} |
Sorry, the diff of this file is not supported yet
81977
6
1079
+ Added@snyk/dep-graph@1.19.3
+ Added@snyk/dep-graph@1.19.3(transitive)
+ Addedbuffer-from@1.1.2(transitive)
+ Addedlodash.isequal@4.5.0(transitive)
+ Addedobject-hash@2.2.0(transitive)
+ Addedsemver@6.3.1(transitive)
+ Addedsource-map@0.6.1(transitive)
+ Addedsource-map-support@0.5.21(transitive)