1
- // import {exec} from "child_process";
2
- import { execSync } from "node:child_process"
3
1
import fs from 'node:fs'
4
2
import { EOL } from "os" ;
5
- import { getCustom , getCustomPath , handleSpacesInPath } from "../tools.js" ;
3
+ import { getCustom , getCustomPath , invokeCommand } from "../tools.js" ;
6
4
import path from 'node:path'
7
5
import Sbom from '../sbom.js'
8
6
import { PackageURL } from 'packageurl-js'
@@ -64,10 +62,6 @@ function provideComponent(manifest, opts = {}) {
64
62
}
65
63
}
66
64
67
- function getGoGraphCommand ( goBin ) {
68
- return `${ handleSpacesInPath ( goBin ) } mod graph ` ;
69
- }
70
-
71
65
/**
72
66
*
73
67
* @param {string } edge containing an edge of direct graph of source dependency (parent) and target dependency (child)
@@ -85,36 +79,21 @@ function getChildVertexFromEdge(edge) {
85
79
return edge . split ( " " ) [ 1 ] ;
86
80
}
87
81
88
-
89
- function getGoModGraph ( goGraphCommand , options ) {
90
- return execSync ( goGraphCommand , options ) . toString ( )
91
- //
92
- // let result = ""
93
- // return new Promise((resolveF => {
94
- // child.stdout.on("data", (x) => result+=x)
95
- // child.stderr.on("data", (x) => result+=x)
96
- // child.on("exit", () => resolveF(result))
97
- // }))
98
- }
99
-
100
82
/**
101
83
*
102
84
* @param line one row from go.mod file
103
85
* @return {boolean } whether line from go.mod should be considered as ignored or not
104
86
*/
105
87
function ignoredLine ( line ) {
106
88
let result = false
107
- if ( line . match ( ".*exhortignore.*" ) )
108
- {
109
- if ( line . match ( ".+//\\s*exhortignore" ) || line . match ( ".+//\\sindirect (//)?\\s*exhortignore" ) )
110
- {
89
+ if ( line . match ( ".*exhortignore.*" ) ) {
90
+ if ( line . match ( ".+//\\s*exhortignore" ) || line . match ( ".+//\\sindirect (//)?\\s*exhortignore" ) ) {
111
91
let trimmedRow = line . trim ( )
112
92
if ( ! trimmedRow . startsWith ( "module " ) && ! trimmedRow . startsWith ( "go " ) && ! trimmedRow . startsWith ( "require (" ) && ! trimmedRow . startsWith ( "require(" )
113
93
&& ! trimmedRow . startsWith ( "exclude " ) && ! trimmedRow . startsWith ( "replace " ) && ! trimmedRow . startsWith ( "retract " ) && ! trimmedRow . startsWith ( "use " )
114
94
&& ! trimmedRow . includes ( "=>" ) )
115
95
{
116
- if ( trimmedRow . startsWith ( "require " ) || trimmedRow . match ( "^[a-z.0-9/-]+\\s{1,2}[vV][0-9]\\.[0-9](\\.[0-9]){0,2}.*" ) )
117
- {
96
+ if ( trimmedRow . startsWith ( "require " ) || trimmedRow . match ( "^[a-z.0-9/-]+\\s{1,2}[vV][0-9]\\.[0-9](\\.[0-9]){0,2}.*" ) ) {
118
97
result = true
119
98
}
120
99
}
@@ -266,32 +245,34 @@ function getSBOM(manifest, opts = {}, includeTransitive) {
266
245
// get custom goBin path
267
246
let goBin = getCustomPath ( 'go' , opts )
268
247
// verify goBin is accessible
269
- execSync ( `${ handleSpacesInPath ( goBin ) } version` , err => {
270
- if ( err ) {
271
- throw new Error ( 'go binary is not accessible' )
248
+ try {
249
+ invokeCommand ( goBin , [ 'version' ] )
250
+ } catch ( error ) {
251
+ if ( error . code === 'ENOENT' ) {
252
+ throw new Error ( `go binary is not accessible at "${ goBin } "` )
272
253
}
273
- } )
254
+ throw new Error ( `failed to check for go binary` , { cause : error } )
255
+ }
274
256
let manifestDir = path . dirname ( manifest )
275
- let goGraphCommand = getGoGraphCommand ( goBin )
276
- let options = { cwd : manifestDir }
277
- let goGraphOutput
278
- goGraphOutput = getGoModGraph ( goGraphCommand , options ) ;
257
+ try {
258
+ var goGraphOutput = invokeCommand ( goBin , [ 'mod' , 'graph' ] , { cwd : manifestDir } ) . toString ( )
259
+ } catch ( error ) {
260
+ throw new Error ( 'failed to invoke go binary for module graph' , { cause : error } )
261
+ }
279
262
let ignoredDeps = getIgnoredDeps ( manifest ) ;
280
263
let allIgnoredDeps = ignoredDeps . map ( ( dep ) => dep . toString ( ) )
281
264
let sbom = new Sbom ( ) ;
282
265
let rows = goGraphOutput . split ( getLineSeparatorGolang ( ) ) ;
283
266
let root = getParentVertexFromEdge ( rows [ 0 ] )
284
- let matchManifestVersions = getCustom ( "MATCH_MANIFEST_VERSIONS" , "false" , opts ) ;
267
+ let matchManifestVersions = getCustom ( "MATCH_MANIFEST_VERSIONS" , "false" , opts ) ;
285
268
if ( matchManifestVersions === "true" ) {
286
- {
287
- performManifestVersionsCheck ( root , rows , manifest )
288
- }
269
+ performManifestVersionsCheck ( root , rows , manifest )
289
270
}
290
- let mainModule = toPurl ( root , "@" , undefined )
271
+
272
+ const mainModule = toPurl ( root , "@" , undefined )
291
273
sbom . addRoot ( mainModule )
292
- let exhortGoMvsLogicEnabled = getCustom ( "EXHORT_GO_MVS_LOGIC_ENABLED" , "false" , opts )
293
- if ( includeTransitive && exhortGoMvsLogicEnabled === "true" )
294
- {
274
+ const exhortGoMvsLogicEnabled = getCustom ( "EXHORT_GO_MVS_LOGIC_ENABLED" , "false" , opts )
275
+ if ( includeTransitive && exhortGoMvsLogicEnabled === "true" ) {
295
276
rows = getFinalPackagesVersionsForModule ( rows , manifest , goBin )
296
277
}
297
278
if ( includeTransitive ) {
@@ -341,22 +322,16 @@ function getSBOM(manifest, opts = {}, includeTransitive) {
341
322
function toPurl ( dependency , delimiter , qualifiers ) {
342
323
let lastSlashIndex = dependency . lastIndexOf ( "/" ) ;
343
324
let pkg
344
- if ( lastSlashIndex === - 1 )
345
- {
325
+ if ( lastSlashIndex === - 1 ) {
346
326
let splitParts = dependency . split ( delimiter ) ;
347
327
pkg = new PackageURL ( ecosystem , undefined , splitParts [ 0 ] , splitParts [ 1 ] , qualifiers , undefined )
348
- }
349
- else
350
- {
328
+ } else {
351
329
let namespace = dependency . slice ( 0 , lastSlashIndex )
352
330
let dependencyAndVersion = dependency . slice ( lastSlashIndex + 1 )
353
331
let parts = dependencyAndVersion . split ( delimiter ) ;
354
- if ( parts . length === 2 )
355
- {
332
+ if ( parts . length === 2 ) {
356
333
pkg = new PackageURL ( ecosystem , namespace , parts [ 0 ] , parts [ 1 ] , qualifiers , undefined ) ;
357
- }
358
- else
359
- {
334
+ } else {
360
335
pkg = new PackageURL ( ecosystem , namespace , parts [ 0 ] , defaultMainModuleVersion , qualifiers , undefined ) ;
361
336
}
362
337
}
@@ -373,8 +348,14 @@ function toPurl(dependency, delimiter, qualifiers) {
373
348
function getFinalPackagesVersionsForModule ( rows , manifestPath , goBin ) {
374
349
let manifestDir = path . dirname ( manifestPath )
375
350
let options = { cwd : manifestDir }
376
- execSync ( `${ handleSpacesInPath ( goBin ) } mod download` , options )
377
- let finalVersionsForAllModules = execSync ( `${ handleSpacesInPath ( goBin ) } list -m all` , options ) . toString ( )
351
+ // TODO: determine whether this is necessary
352
+ try {
353
+ invokeCommand ( goBin , [ 'mod' , 'download' ] , options )
354
+ var finalVersionsForAllModules = invokeCommand ( goBin , [ 'list' , '-m' , 'all' ] , options ) . toString ( )
355
+ } catch ( error ) {
356
+ throw new Error ( 'failed to list all modules' , { cause : error } )
357
+ }
358
+
378
359
let finalVersionModules = new Map ( )
379
360
finalVersionsForAllModules . split ( getLineSeparatorGolang ( ) ) . filter ( string => string . trim ( ) !== "" )
380
361
. filter ( string => string . trim ( ) . split ( " " ) . length === 2 )
@@ -418,12 +399,3 @@ function getLineSeparatorGolang() {
418
399
let reg = / \n | \r \n /
419
400
return reg
420
401
}
421
-
422
- // /**
423
- // *
424
- // * @param {string } fullPackage - full package with its name and version-
425
- // * @return {string } package version only
426
- // */
427
- // function getVersionOfPackage(fullPackage) {
428
- // return fullPackage.split("@")[1]
429
- // }
0 commit comments