From 20a60823db545eaa4e3ef43af9a9409486a53c17 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Mon, 15 Apr 2024 18:08:34 -0400 Subject: [PATCH] chore(biome): fix useless else cases Signed-off-by: Adam Setch --- biome.json | 3 +- docker.js | 69 ++- envcontext.js | 11 +- index.js | 1287 ++++++++++++++++++++++++------------------------- utils.js | 132 +++-- 5 files changed, 731 insertions(+), 771 deletions(-) diff --git a/biome.json b/biome.json index 62488cfc6..8da61be65 100644 --- a/biome.json +++ b/biome.json @@ -17,8 +17,7 @@ }, "style": { "noParameterAssign": "off", - "noUnusedTemplateLiteral": "off", - "noUselessElse": "off" + "noUnusedTemplateLiteral": "off" }, "suspicious": { "noDoubleEquals": "off", diff --git a/docker.js b/docker.js index 1a0ae19e5..ab0b626dd 100644 --- a/docker.js +++ b/docker.js @@ -181,7 +181,8 @@ const getDefaultOptions = (forRegistry) => { }; authTokenSet = true; break; - } else if (configJson.credsStore) { + } + if (configJson.credsStore) { const helperAuthToken = getCredsFromHelper( configJson.credsStore, serverAddress, @@ -288,7 +289,8 @@ const getDefaultOptions = (forRegistry) => { export const getConnection = async (options, forRegistry) => { if (isContainerd) { return undefined; - } else if (!dockerConn) { + } + if (!dockerConn) { const defaultOptions = getDefaultOptions(forRegistry); const opts = Object.assign( {}, @@ -542,29 +544,26 @@ export const getImage = async (fullImageName) => { console.log(result.stderr); } return localData; - } else { - result = spawnSync(dockerCmd, ["inspect", fullImageName], { - encoding: "utf-8", - }); - if (result.status !== 0 || result.error) { - console.log(result.stderr); - return localData; - } else { - try { - const stdout = result.stdout; - if (stdout) { - const inspectData = JSON.parse(Buffer.from(stdout).toString()); - if (inspectData && Array.isArray(inspectData)) { - return inspectData[0]; - } else { - return inspectData; - } - } - } catch (err) { - // continue regardless of error - console.log(err); + } + result = spawnSync(dockerCmd, ["inspect", fullImageName], { + encoding: "utf-8", + }); + if (result.status !== 0 || result.error) { + console.log(result.stderr); + return localData; + } + try { + const stdout = result.stdout; + if (stdout) { + const inspectData = JSON.parse(Buffer.from(stdout).toString()); + if (inspectData && Array.isArray(inspectData)) { + return inspectData[0]; } + return inspectData; } + } catch (err) { + // continue regardless of error + console.log(err); } } try { @@ -789,7 +788,8 @@ export const exportArchive = async (fullImageName) => { }; exportData.pkgPathList = getPkgPathList(exportData, lastWorkingDir); return exportData; - } else if (existsSync(manifestFile)) { + } + if (existsSync(manifestFile)) { // docker manifest file return await extractFromManifest( manifestFile, @@ -797,9 +797,8 @@ export const exportArchive = async (fullImageName) => { tempDir, allLayersExplodedDir, ); - } else { - console.log(`Unable to extract image archive to ${tempDir}`); } + console.log(`Unable to extract image archive to ${tempDir}`); } catch (err) { console.log(err); } @@ -947,14 +946,13 @@ export const exportImage = async (fullImageName) => { console.log(result.stdout, result.stderr); } return localData; - } else { - await extractTar(imageTarFile, tempDir); - if (DEBUG_MODE) { - console.log(`Cleaning up ${imageTarFile}`); - } - if (rmSync) { - rmSync(imageTarFile, { force: true }); - } + } + await extractTar(imageTarFile, tempDir); + if (DEBUG_MODE) { + console.log(`Cleaning up ${imageTarFile}`); + } + if (rmSync) { + rmSync(imageTarFile, { force: true }); } } else { const client = await getConnection({}, registry); @@ -1028,9 +1026,8 @@ export const exportImage = async (fullImageName) => { tempDir, allLayersExplodedDir, ); - } else { - console.log(`Unable to export image to ${tempDir}`); } + console.log(`Unable to export image to ${tempDir}`); return undefined; }; diff --git a/envcontext.js b/envcontext.js index 06f664f79..778fa9718 100644 --- a/envcontext.js +++ b/envcontext.js @@ -319,11 +319,10 @@ const getCommandOutput = (cmd, dir, args) => { }); if (result.status !== 0 || result.error) { return undefined; - } else { - const stdout = result.stdout; - if (stdout) { - const cmdOutput = Buffer.from(stdout).toString(); - return cmdOutput.trim(); - } + } + const stdout = result.stdout; + if (stdout) { + const cmdOutput = Buffer.from(stdout).toString(); + return cmdOutput.trim(); } }; diff --git a/index.js b/index.js index bbfd19776..dfe903472 100644 --- a/index.js +++ b/index.js @@ -245,7 +245,8 @@ const determineParentComponent = (options) => { let parentComponent = undefined; if (options.parentComponent && Object.keys(options.parentComponent).length) { return options.parentComponent; - } else if (options.projectName && options.projectVersion) { + } + if (options.projectName && options.projectVersion) { parentComponent = { group: options.projectGroup || "", name: options.projectName, @@ -1192,732 +1193,707 @@ export async function createJavaBom(path, options) { dependencies, parentComponent, }); - } else { - // maven - pom.xml - const pomFiles = getAllFiles( - path, - `${options.multiProject ? "**/" : ""}pom.xml`, - options, - ); - let bomJsonFiles = []; - if ( - pomFiles?.length && - !["scala", "sbt", "gradle"].includes(options.projectType) - ) { - const cdxMavenPlugin = - process.env.CDX_MAVEN_PLUGIN || - "org.cyclonedx:cyclonedx-maven-plugin:2.8.0"; - const cdxMavenGoal = process.env.CDX_MAVEN_GOAL || "makeAggregateBom"; - let mvnArgs = [`${cdxMavenPlugin}:${cdxMavenGoal}`, "-DoutputName=bom"]; - if (includeMavenTestScope) { - mvnArgs.push("-DincludeTestScope=true"); - } - // By using quiet mode we can reduce the maxBuffer used and avoid crashes - if (!DEBUG_MODE) { - mvnArgs.push("-q"); - } - // Support for passing additional settings and profile to maven - if (process.env.MVN_ARGS) { - const addArgs = process.env.MVN_ARGS.split(" "); - mvnArgs = mvnArgs.concat(addArgs); - } - // specVersion 1.4 doesn't support externalReferences.type=disribution-intake - // so we need to run the plugin with the correct version - if (options.specVersion === 1.4) { - mvnArgs = mvnArgs.concat("-DschemaVersion=1.4"); - } - for (const f of pomFiles) { - const basePath = dirname(f); - const settingsXml = join(basePath, "settings.xml"); - if (existsSync(settingsXml)) { - console.log( - `maven settings.xml found in ${basePath}. Please set the MVN_ARGS environment variable based on the full mvn build command used for this project.\nExample: MVN_ARGS='--settings ${settingsXml}'`, - ); + } + // maven - pom.xml + const pomFiles = getAllFiles( + path, + `${options.multiProject ? "**/" : ""}pom.xml`, + options, + ); + let bomJsonFiles = []; + if ( + pomFiles?.length && + !["scala", "sbt", "gradle"].includes(options.projectType) + ) { + const cdxMavenPlugin = + process.env.CDX_MAVEN_PLUGIN || + "org.cyclonedx:cyclonedx-maven-plugin:2.8.0"; + const cdxMavenGoal = process.env.CDX_MAVEN_GOAL || "makeAggregateBom"; + let mvnArgs = [`${cdxMavenPlugin}:${cdxMavenGoal}`, "-DoutputName=bom"]; + if (includeMavenTestScope) { + mvnArgs.push("-DincludeTestScope=true"); + } + // By using quiet mode we can reduce the maxBuffer used and avoid crashes + if (!DEBUG_MODE) { + mvnArgs.push("-q"); + } + // Support for passing additional settings and profile to maven + if (process.env.MVN_ARGS) { + const addArgs = process.env.MVN_ARGS.split(" "); + mvnArgs = mvnArgs.concat(addArgs); + } + // specVersion 1.4 doesn't support externalReferences.type=disribution-intake + // so we need to run the plugin with the correct version + if (options.specVersion === 1.4) { + mvnArgs = mvnArgs.concat("-DschemaVersion=1.4"); + } + for (const f of pomFiles) { + const basePath = dirname(f); + const settingsXml = join(basePath, "settings.xml"); + if (existsSync(settingsXml)) { + console.log( + `maven settings.xml found in ${basePath}. Please set the MVN_ARGS environment variable based on the full mvn build command used for this project.\nExample: MVN_ARGS='--settings ${settingsXml}'`, + ); + } + const mavenCmd = getMavenCommand(basePath, path); + // Should we attempt to resolve class names + if (options.resolveClass || options.deep) { + const tmpjarNSMapping = await collectMvnDependencies( + mavenCmd, + basePath, + true, + false, + ); + if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) { + jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping }; } - const mavenCmd = getMavenCommand(basePath, path); - // Should we attempt to resolve class names - if (options.resolveClass || options.deep) { - const tmpjarNSMapping = await collectMvnDependencies( - mavenCmd, - basePath, - true, - false, - ); - if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) { - jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping }; - } + } + console.log(`Executing '${mavenCmd} ${mvnArgs.join(" ")}' in`, basePath); + let result = spawnSync(mavenCmd, mvnArgs, { + cwd: basePath, + shell: true, + encoding: "utf-8", + timeout: TIMEOUT_MS, + maxBuffer: MAX_BUFFER, + }); + // Check if the cyclonedx plugin created the required bom.json file + // Sometimes the plugin fails silently for complex maven projects + bomJsonFiles = getAllFiles(path, "**/target/*.json", options); + // Check if the bom json files got created in a directory other than target + if (!bomJsonFiles.length) { + bomJsonFiles = getAllFiles(path, "**/bom*.json", options); + } + const bomGenerated = bomJsonFiles.length; + if (!bomGenerated || result.status !== 0 || result.error) { + const tempDir = mkdtempSync(join(tmpdir(), "cdxmvn-")); + const tempMvnTree = join(tempDir, "mvn-tree.txt"); + let mvnTreeArgs = ["dependency:tree", `-DoutputFile=${tempMvnTree}`]; + if (process.env.MVN_ARGS) { + const addArgs = process.env.MVN_ARGS.split(" "); + mvnTreeArgs = mvnTreeArgs.concat(addArgs); } console.log( - `Executing '${mavenCmd} ${mvnArgs.join(" ")}' in`, - basePath, + `Fallback to executing ${mavenCmd} ${mvnTreeArgs.join(" ")}`, ); - let result = spawnSync(mavenCmd, mvnArgs, { + result = spawnSync(mavenCmd, mvnTreeArgs, { cwd: basePath, shell: true, encoding: "utf-8", timeout: TIMEOUT_MS, maxBuffer: MAX_BUFFER, }); - // Check if the cyclonedx plugin created the required bom.json file - // Sometimes the plugin fails silently for complex maven projects - bomJsonFiles = getAllFiles(path, "**/target/*.json", options); - // Check if the bom json files got created in a directory other than target - if (!bomJsonFiles.length) { - bomJsonFiles = getAllFiles(path, "**/bom*.json", options); - } - const bomGenerated = bomJsonFiles.length; - if (!bomGenerated || result.status !== 0 || result.error) { - const tempDir = mkdtempSync(join(tmpdir(), "cdxmvn-")); - const tempMvnTree = join(tempDir, "mvn-tree.txt"); - let mvnTreeArgs = ["dependency:tree", `-DoutputFile=${tempMvnTree}`]; - if (process.env.MVN_ARGS) { - const addArgs = process.env.MVN_ARGS.split(" "); - mvnTreeArgs = mvnTreeArgs.concat(addArgs); - } - console.log( - `Fallback to executing ${mavenCmd} ${mvnTreeArgs.join(" ")}`, - ); - result = spawnSync(mavenCmd, mvnTreeArgs, { - cwd: basePath, - shell: true, - encoding: "utf-8", - timeout: TIMEOUT_MS, - maxBuffer: MAX_BUFFER, - }); - if (result.status !== 0 || result.error) { - // Our approach to recursively invoking the maven plugin for each sub-module is bound to result in failures - // These could be due to a range of reasons that are covered below. - if (pomFiles.length === 1 || DEBUG_MODE) { - console.error(result.stdout, result.stderr); + if (result.status !== 0 || result.error) { + // Our approach to recursively invoking the maven plugin for each sub-module is bound to result in failures + // These could be due to a range of reasons that are covered below. + if (pomFiles.length === 1 || DEBUG_MODE) { + console.error(result.stdout, result.stderr); + console.log( + "Resolve the above maven error. This could be due to the following:\n", + ); + if ( + result.stdout && + (result.stdout.includes("Non-resolvable parent POM") || + result.stdout.includes("points at wrong local POM")) + ) { console.log( - "Resolve the above maven error. This could be due to the following:\n", + "1. Check if the pom.xml contains valid settings such `parent.relativePath` to make mvn command work from within the sub-directory.", ); - if ( - result.stdout && - (result.stdout.includes("Non-resolvable parent POM") || - result.stdout.includes("points at wrong local POM")) - ) { - console.log( - "1. Check if the pom.xml contains valid settings such `parent.relativePath` to make mvn command work from within the sub-directory.", - ); - } else if ( - result.stdout && - (result.stdout.includes("Could not resolve dependencies") || - result.stdout.includes("no dependency information available")) - ) { - console.log( - "1. Try building the project with 'mvn package -Dmaven.test.skip=true' using the correct version of Java and maven before invoking cdxgen.", - ); - } else if ( - result.stdout?.includes( - "Could not resolve target platform specification", - ) - ) { - console.log( - "1. Some projects can be built only from the root directory. Invoke cdxgen with --no-recurse option", - ); - } else { - console.log( - "1. Java version requirement: cdxgen container image bundles Java 21 with maven 3.9 which might be incompatible.", - ); - } + } else if ( + result.stdout && + (result.stdout.includes("Could not resolve dependencies") || + result.stdout.includes("no dependency information available")) + ) { console.log( - "2. Private dependencies cannot be downloaded: Check if any additional arguments must be passed to maven and set them via MVN_ARGS environment variable.", + "1. Try building the project with 'mvn package -Dmaven.test.skip=true' using the correct version of Java and maven before invoking cdxgen.", ); + } else if ( + result.stdout?.includes( + "Could not resolve target platform specification", + ) + ) { console.log( - "3. Check if all required environment variables including any maven profile arguments are passed correctly to this tool.", + "1. Some projects can be built only from the root directory. Invoke cdxgen with --no-recurse option", + ); + } else { + console.log( + "1. Java version requirement: cdxgen container image bundles Java 21 with maven 3.9 which might be incompatible.", ); } - // Do not fall back to methods that can produce incomplete results when failOnError is set - options.failOnError && process.exit(1); console.log( - "\nFalling back to manual pom.xml parsing. The result would be incomplete!", + "2. Private dependencies cannot be downloaded: Check if any additional arguments must be passed to maven and set them via MVN_ARGS environment variable.", + ); + console.log( + "3. Check if all required environment variables including any maven profile arguments are passed correctly to this tool.", ); - const dlist = parsePom(f); - if (dlist?.length) { - pkgList = pkgList.concat(dlist); - } - } else { - if (existsSync(tempMvnTree)) { - const mvnTreeString = readFileSync(tempMvnTree, { - encoding: "utf-8", - }); - const parsedList = parseMavenTree(mvnTreeString); - const dlist = parsedList.pkgList; - parentComponent = dlist.splice(0, 1)[0]; - parentComponent.type = "application"; - if (dlist?.length) { - pkgList = pkgList.concat(dlist); - } - if (parsedList.dependenciesList && parsedList.dependenciesList) { - dependencies = dependencies.concat(parsedList.dependenciesList); - } - unlinkSync(tempMvnTree); - } } - } - } // for - for (const abjson of bomJsonFiles) { - let bomJsonObj = undefined; - try { - if (DEBUG_MODE) { - console.log(`Extracting data from generated bom file ${abjson}`); + // Do not fall back to methods that can produce incomplete results when failOnError is set + options.failOnError && process.exit(1); + console.log( + "\nFalling back to manual pom.xml parsing. The result would be incomplete!", + ); + const dlist = parsePom(f); + if (dlist?.length) { + pkgList = pkgList.concat(dlist); } - bomJsonObj = JSON.parse( - readFileSync(abjson, { + } else { + if (existsSync(tempMvnTree)) { + const mvnTreeString = readFileSync(tempMvnTree, { encoding: "utf-8", - }), - ); - if (bomJsonObj) { - if ( - !tools && - bomJsonObj.metadata && - bomJsonObj.metadata.tools && - Array.isArray(bomJsonObj.metadata.tools) - ) { - tools = bomJsonObj.metadata.tools; - } - if ( - bomJsonObj.metadata?.component && - !Object.keys(parentComponent).length - ) { - parentComponent = bomJsonObj.metadata.component; - options.parentComponent = parentComponent; - pkgList = []; - } - if (bomJsonObj.components) { - pkgList = pkgList.concat(bomJsonObj.components); - } - if (bomJsonObj.dependencies) { - dependencies = mergeDependencies( - dependencies, - bomJsonObj.dependencies, - parentComponent, - ); + }); + const parsedList = parseMavenTree(mvnTreeString); + const dlist = parsedList.pkgList; + parentComponent = dlist.splice(0, 1)[0]; + parentComponent.type = "application"; + if (dlist?.length) { + pkgList = pkgList.concat(dlist); } - } - } catch (err) { - if (options.failOnError || DEBUG_MODE) { - console.log(err); - options.failOnError && process.exit(1); - } - } - } - if (pkgList) { - pkgList = trimComponents(pkgList); - pkgList = await getMvnMetadata(pkgList, jarNSMapping); - return buildBomNSData(options, pkgList, "maven", { - src: path, - filename: pomFiles.join(", "), - nsMapping: jarNSMapping, - dependencies, - parentComponent, - tools, - }); - } else if (bomJsonFiles.length) { - const bomNSData = {}; - bomNSData.bomJsonFiles = bomJsonFiles; - bomNSData.nsMapping = jarNSMapping; - bomNSData.dependencies = dependencies; - bomNSData.parentComponent = parentComponent; - return bomNSData; - } - } - // gradle - const gradleFiles = getAllFiles( - path, - `${options.multiProject ? "**/" : ""}build.gradle*`, - options, - ); - const allProjects = []; - const allProjectsAddedPurls = []; - const rootDependsOn = []; - // Execute gradle properties - if ( - gradleFiles?.length && - !["scala", "sbt"].includes(options.projectType) - ) { - let retMap = executeGradleProperties(path, null, null); - const allProjectsStr = retMap.projects || []; - const rootProject = retMap.rootProject; - if (rootProject) { - parentComponent = { - name: rootProject, - type: "application", - ...retMap.metadata, - }; - const parentPurl = new PackageURL( - "maven", - parentComponent.group || "", - parentComponent.name, - parentComponent.version, - { type: "jar" }, - null, - ).toString(); - parentComponent["purl"] = parentPurl; - parentComponent["bom-ref"] = decodeURIComponent(parentPurl); - } - // Get the sub-project properties and set the root dependencies - if (allProjectsStr?.length) { - for (const spstr of allProjectsStr) { - retMap = executeGradleProperties(path, null, spstr); - const rootSubProject = retMap.rootProject; - if (rootSubProject) { - const rspName = rootSubProject.replace(/^:/, ""); - const rootSubProjectObj = { - name: rspName, - type: "application", - qualifiers: { type: "jar" }, - ...retMap.metadata, - }; - const rootSubProjectPurl = new PackageURL( - "maven", - rootSubProjectObj.group?.length - ? rootSubProjectObj.group - : parentComponent.group, - rootSubProjectObj.name, - retMap.metadata.version && retMap.metadata.version !== "latest" - ? retMap.metadata.version - : parentComponent.version, - rootSubProjectObj.qualifiers, - null, - ).toString(); - rootSubProjectObj["purl"] = rootSubProjectPurl; - rootSubProjectObj["bom-ref"] = - decodeURIComponent(rootSubProjectPurl); - if (!allProjectsAddedPurls.includes(rootSubProjectPurl)) { - allProjects.push(rootSubProjectObj); - rootDependsOn.push(rootSubProjectPurl); - allProjectsAddedPurls.push(rootSubProjectPurl); + if (parsedList.dependenciesList && parsedList.dependenciesList) { + dependencies = dependencies.concat(parsedList.dependenciesList); } + unlinkSync(tempMvnTree); } } - // Bug #317 fix - parentComponent.components = allProjects.flatMap((s) => { - delete s.qualifiers; - delete s.evidence; - return s; - }); - dependencies.push({ - ref: parentComponent["bom-ref"], - dependsOn: rootDependsOn, - }); } - } - if ( - gradleFiles?.length && - options.installDeps && - !["scala", "sbt"].includes(options.projectType) - ) { - const gradleCmd = getGradleCommand(path, null); - const defaultDepTaskArgs = ["-q", "--console", "plain", "--build-cache"]; - allProjects.push(parentComponent); - let depTaskWithArgs = ["dependencies"]; - if (process.env.GRADLE_DEPENDENCY_TASK) { - depTaskWithArgs = process.env.GRADLE_DEPENDENCY_TASK.split(" "); - } - for (const sp of allProjects) { - let gradleDepArgs = [ - sp.purl === parentComponent.purl - ? depTaskWithArgs[0] - : `:${sp.name}:${depTaskWithArgs[0]}`, - ]; - gradleDepArgs = gradleDepArgs - .concat(depTaskWithArgs.slice(1)) - .concat(defaultDepTaskArgs); - // Support custom GRADLE_ARGS such as --configuration runtimeClassPath (used for all tasks) - if (process.env.GRADLE_ARGS) { - const addArgs = process.env.GRADLE_ARGS.split(" "); - gradleDepArgs = gradleDepArgs.concat(addArgs); - } - // gradle args only for the dependencies task - if (process.env.GRADLE_ARGS_DEPENDENCIES) { - const addArgs = process.env.GRADLE_ARGS_DEPENDENCIES.split(" "); - gradleDepArgs = gradleDepArgs.concat(addArgs); + } // for + for (const abjson of bomJsonFiles) { + let bomJsonObj = undefined; + try { + if (DEBUG_MODE) { + console.log(`Extracting data from generated bom file ${abjson}`); } - console.log( - "Executing", - gradleCmd, - gradleDepArgs.join(" "), - "in", - path, + bomJsonObj = JSON.parse( + readFileSync(abjson, { + encoding: "utf-8", + }), ); - const sresult = spawnSync(gradleCmd, gradleDepArgs, { - cwd: path, - encoding: "utf-8", - timeout: TIMEOUT_MS, - maxBuffer: MAX_BUFFER, - }); - if (sresult.status !== 0 || sresult.error) { - if (options.failOnError || DEBUG_MODE) { - console.error(sresult.stdout, sresult.stderr); + if (bomJsonObj) { + if ( + !tools && + bomJsonObj.metadata && + bomJsonObj.metadata.tools && + Array.isArray(bomJsonObj.metadata.tools) + ) { + tools = bomJsonObj.metadata.tools; } - options.failOnError && process.exit(1); - } - const sstdout = sresult.stdout; - if (sstdout) { - const cmdOutput = Buffer.from(sstdout).toString(); - const parsedList = parseGradleDep( - cmdOutput, - sp.group || parentComponent.group, - sp.name, - sp.version?.length && sp.version !== "latest" - ? sp.version - : parentComponent.version, - ); - const dlist = parsedList.pkgList; - if (parsedList.dependenciesList && parsedList.dependenciesList) { + if ( + bomJsonObj.metadata?.component && + !Object.keys(parentComponent).length + ) { + parentComponent = bomJsonObj.metadata.component; + options.parentComponent = parentComponent; + pkgList = []; + } + if (bomJsonObj.components) { + pkgList = pkgList.concat(bomJsonObj.components); + } + if (bomJsonObj.dependencies) { dependencies = mergeDependencies( dependencies, - parsedList.dependenciesList, + bomJsonObj.dependencies, parentComponent, ); } - if (dlist?.length) { - if (DEBUG_MODE) { - console.log( - "Found", - dlist.length, - "packages in gradle project", - sp.name, - ); - } - pkgList = pkgList.concat(dlist); - } - } - } // for - if (pkgList.length) { - if (parentComponent.components?.length) { - for (const subProj of parentComponent.components) { - pkgList = pkgList.filter( - (pkg) => pkg["bom-ref"] !== subProj["bom-ref"], - ); - } } - console.log( - "Obtained", - pkgList.length, - "from this gradle project. De-duping this list ...", - ); - } else { - console.log( - "No packages found. Set the environment variable 'CDXGEN_DEBUG_MODE=debug' to troubleshoot any gradle related errors.", - ); - options.failOnError && process.exit(1); - } - // Should we attempt to resolve class names - if (options.resolveClass || options.deep) { - const tmpjarNSMapping = await collectJarNS(GRADLE_CACHE_DIR); - if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) { - jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping }; + } catch (err) { + if (options.failOnError || DEBUG_MODE) { + console.log(err); + options.failOnError && process.exit(1); } } + } + if (pkgList) { + pkgList = trimComponents(pkgList); pkgList = await getMvnMetadata(pkgList, jarNSMapping); return buildBomNSData(options, pkgList, "maven", { src: path, - filename: gradleFiles.join(", "), + filename: pomFiles.join(", "), nsMapping: jarNSMapping, dependencies, parentComponent, + tools, }); } + if (bomJsonFiles.length) { + const bomNSData = {}; + bomNSData.bomJsonFiles = bomJsonFiles; + bomNSData.nsMapping = jarNSMapping; + bomNSData.dependencies = dependencies; + bomNSData.parentComponent = parentComponent; + return bomNSData; + } + } + // gradle + const gradleFiles = getAllFiles( + path, + `${options.multiProject ? "**/" : ""}build.gradle*`, + options, + ); + const allProjects = []; + const allProjectsAddedPurls = []; + const rootDependsOn = []; + // Execute gradle properties + if (gradleFiles?.length && !["scala", "sbt"].includes(options.projectType)) { + let retMap = executeGradleProperties(path, null, null); + const allProjectsStr = retMap.projects || []; + const rootProject = retMap.rootProject; + if (rootProject) { + parentComponent = { + name: rootProject, + type: "application", + ...retMap.metadata, + }; + const parentPurl = new PackageURL( + "maven", + parentComponent.group || "", + parentComponent.name, + parentComponent.version, + { type: "jar" }, + null, + ).toString(); + parentComponent["purl"] = parentPurl; + parentComponent["bom-ref"] = decodeURIComponent(parentPurl); + } + // Get the sub-project properties and set the root dependencies + if (allProjectsStr?.length) { + for (const spstr of allProjectsStr) { + retMap = executeGradleProperties(path, null, spstr); + const rootSubProject = retMap.rootProject; + if (rootSubProject) { + const rspName = rootSubProject.replace(/^:/, ""); + const rootSubProjectObj = { + name: rspName, + type: "application", + qualifiers: { type: "jar" }, + ...retMap.metadata, + }; + const rootSubProjectPurl = new PackageURL( + "maven", + rootSubProjectObj.group?.length + ? rootSubProjectObj.group + : parentComponent.group, + rootSubProjectObj.name, + retMap.metadata.version && retMap.metadata.version !== "latest" + ? retMap.metadata.version + : parentComponent.version, + rootSubProjectObj.qualifiers, + null, + ).toString(); + rootSubProjectObj["purl"] = rootSubProjectPurl; + rootSubProjectObj["bom-ref"] = decodeURIComponent(rootSubProjectPurl); + if (!allProjectsAddedPurls.includes(rootSubProjectPurl)) { + allProjects.push(rootSubProjectObj); + rootDependsOn.push(rootSubProjectPurl); + allProjectsAddedPurls.push(rootSubProjectPurl); + } + } + } + // Bug #317 fix + parentComponent.components = allProjects.flatMap((s) => { + delete s.qualifiers; + delete s.evidence; + return s; + }); + dependencies.push({ + ref: parentComponent["bom-ref"], + dependsOn: rootDependsOn, + }); + } + } + if ( + gradleFiles?.length && + options.installDeps && + !["scala", "sbt"].includes(options.projectType) + ) { + const gradleCmd = getGradleCommand(path, null); + const defaultDepTaskArgs = ["-q", "--console", "plain", "--build-cache"]; + allProjects.push(parentComponent); + let depTaskWithArgs = ["dependencies"]; + if (process.env.GRADLE_DEPENDENCY_TASK) { + depTaskWithArgs = process.env.GRADLE_DEPENDENCY_TASK.split(" "); + } + for (const sp of allProjects) { + let gradleDepArgs = [ + sp.purl === parentComponent.purl + ? depTaskWithArgs[0] + : `:${sp.name}:${depTaskWithArgs[0]}`, + ]; + gradleDepArgs = gradleDepArgs + .concat(depTaskWithArgs.slice(1)) + .concat(defaultDepTaskArgs); + // Support custom GRADLE_ARGS such as --configuration runtimeClassPath (used for all tasks) + if (process.env.GRADLE_ARGS) { + const addArgs = process.env.GRADLE_ARGS.split(" "); + gradleDepArgs = gradleDepArgs.concat(addArgs); + } + // gradle args only for the dependencies task + if (process.env.GRADLE_ARGS_DEPENDENCIES) { + const addArgs = process.env.GRADLE_ARGS_DEPENDENCIES.split(" "); + gradleDepArgs = gradleDepArgs.concat(addArgs); + } + console.log("Executing", gradleCmd, gradleDepArgs.join(" "), "in", path); + const sresult = spawnSync(gradleCmd, gradleDepArgs, { + cwd: path, + encoding: "utf-8", + timeout: TIMEOUT_MS, + maxBuffer: MAX_BUFFER, + }); + if (sresult.status !== 0 || sresult.error) { + if (options.failOnError || DEBUG_MODE) { + console.error(sresult.stdout, sresult.stderr); + } + options.failOnError && process.exit(1); + } + const sstdout = sresult.stdout; + if (sstdout) { + const cmdOutput = Buffer.from(sstdout).toString(); + const parsedList = parseGradleDep( + cmdOutput, + sp.group || parentComponent.group, + sp.name, + sp.version?.length && sp.version !== "latest" + ? sp.version + : parentComponent.version, + ); + const dlist = parsedList.pkgList; + if (parsedList.dependenciesList && parsedList.dependenciesList) { + dependencies = mergeDependencies( + dependencies, + parsedList.dependenciesList, + parentComponent, + ); + } + if (dlist?.length) { + if (DEBUG_MODE) { + console.log( + "Found", + dlist.length, + "packages in gradle project", + sp.name, + ); + } + pkgList = pkgList.concat(dlist); + } + } + } // for + if (pkgList.length) { + if (parentComponent.components?.length) { + for (const subProj of parentComponent.components) { + pkgList = pkgList.filter( + (pkg) => pkg["bom-ref"] !== subProj["bom-ref"], + ); + } + } + console.log( + "Obtained", + pkgList.length, + "from this gradle project. De-duping this list ...", + ); + } else { + console.log( + "No packages found. Set the environment variable 'CDXGEN_DEBUG_MODE=debug' to troubleshoot any gradle related errors.", + ); + options.failOnError && process.exit(1); + } + // Should we attempt to resolve class names + if (options.resolveClass || options.deep) { + const tmpjarNSMapping = await collectJarNS(GRADLE_CACHE_DIR); + if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) { + jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping }; + } + } + pkgList = await getMvnMetadata(pkgList, jarNSMapping); + return buildBomNSData(options, pkgList, "maven", { + src: path, + filename: gradleFiles.join(", "), + nsMapping: jarNSMapping, + dependencies, + parentComponent, + }); + } - // Bazel - // Look for the BUILD file only in the root directory - const bazelFiles = getAllFiles(path, "BUILD", options); - if (bazelFiles?.length && !["scala", "sbt"].includes(options.projectType)) { - let BAZEL_CMD = "bazel"; - if (process.env.BAZEL_HOME) { - BAZEL_CMD = join(process.env.BAZEL_HOME, "bin", "bazel"); - } - for (const f of bazelFiles) { - const basePath = dirname(f); - // Invoke bazel build first - const bazelTarget = process.env.BAZEL_TARGET || ":all"; + // Bazel + // Look for the BUILD file only in the root directory + const bazelFiles = getAllFiles(path, "BUILD", options); + if (bazelFiles?.length && !["scala", "sbt"].includes(options.projectType)) { + let BAZEL_CMD = "bazel"; + if (process.env.BAZEL_HOME) { + BAZEL_CMD = join(process.env.BAZEL_HOME, "bin", "bazel"); + } + for (const f of bazelFiles) { + const basePath = dirname(f); + // Invoke bazel build first + const bazelTarget = process.env.BAZEL_TARGET || ":all"; + console.log("Executing", BAZEL_CMD, "build", bazelTarget, "in", basePath); + let result = spawnSync(BAZEL_CMD, ["build", bazelTarget], { + cwd: basePath, + shell: true, + encoding: "utf-8", + timeout: TIMEOUT_MS, + maxBuffer: MAX_BUFFER, + }); + if (result.status !== 0 || result.error) { + if (result.stderr) { + console.error(result.stdout, result.stderr); + } console.log( - "Executing", - BAZEL_CMD, - "build", - bazelTarget, - "in", - basePath, + "1. Check if bazel is installed and available in PATH.\n2. Try building your app with bazel prior to invoking cdxgen", ); - let result = spawnSync(BAZEL_CMD, ["build", bazelTarget], { + options.failOnError && process.exit(1); + } else { + const target = process.env.BAZEL_TARGET || "//..."; + let query; + let bazelParser; + if (["true", "1"].includes(process.env.BAZEL_USE_ACTION_GRAPH)) { + query = ["aquery", `outputs('.*.jar',deps(${target}))`]; + bazelParser = parseBazelActionGraph; + } else { + query = ["aquery", "--output=textproto", "--skyframe_state"]; + bazelParser = parseBazelSkyframe; + } + + console.log("Executing", BAZEL_CMD, `${query.join(" ")} in`, basePath); + result = spawnSync(BAZEL_CMD, query, { cwd: basePath, - shell: true, encoding: "utf-8", timeout: TIMEOUT_MS, maxBuffer: MAX_BUFFER, }); if (result.status !== 0 || result.error) { - if (result.stderr) { - console.error(result.stdout, result.stderr); - } - console.log( - "1. Check if bazel is installed and available in PATH.\n2. Try building your app with bazel prior to invoking cdxgen", - ); + console.error(result.stdout, result.stderr); options.failOnError && process.exit(1); - } else { - const target = process.env.BAZEL_TARGET || "//..."; - let query; - let bazelParser; - if (["true", "1"].includes(process.env.BAZEL_USE_ACTION_GRAPH)) { - query = ["aquery", `outputs('.*.jar',deps(${target}))`]; - bazelParser = parseBazelActionGraph; - } else { - query = ["aquery", "--output=textproto", "--skyframe_state"]; - bazelParser = parseBazelSkyframe; - } - - console.log( - "Executing", - BAZEL_CMD, - `${query.join(" ")} in`, - basePath, - ); - result = spawnSync(BAZEL_CMD, query, { - cwd: basePath, - encoding: "utf-8", - timeout: TIMEOUT_MS, - maxBuffer: MAX_BUFFER, - }); - if (result.status !== 0 || result.error) { - console.error(result.stdout, result.stderr); - options.failOnError && process.exit(1); - } - const stdout = result.stdout; - if (stdout) { - const cmdOutput = Buffer.from(stdout).toString(); - const dlist = bazelParser(cmdOutput); - if (dlist?.length) { - pkgList = pkgList.concat(dlist); - } else { - console.log( - "No packages were detected.\n1. Build your project using bazel build command before running cdxgen\n2. Try running the bazel aquery command manually to see if skyframe state can be retrieved.", - ); - console.log( - "If your project requires a different query, please file a bug at cyclonedx/cdxgen repo!", - ); - options.failOnError && process.exit(1); - } + } + const stdout = result.stdout; + if (stdout) { + const cmdOutput = Buffer.from(stdout).toString(); + const dlist = bazelParser(cmdOutput); + if (dlist?.length) { + pkgList = pkgList.concat(dlist); } else { - console.log("Bazel unexpectedly didn't produce any output"); + console.log( + "No packages were detected.\n1. Build your project using bazel build command before running cdxgen\n2. Try running the bazel aquery command manually to see if skyframe state can be retrieved.", + ); + console.log( + "If your project requires a different query, please file a bug at cyclonedx/cdxgen repo!", + ); options.failOnError && process.exit(1); } - // FIXME: How do we retrieve jarNSMapping for bazel projects? - pkgList = await getMvnMetadata(pkgList, jarNSMapping); - return buildBomNSData(options, pkgList, "maven", { - src: path, - filename: "BUILD", - nsMapping: {}, - dependencies, - parentComponent, - }); + } else { + console.log("Bazel unexpectedly didn't produce any output"); + options.failOnError && process.exit(1); } + // FIXME: How do we retrieve jarNSMapping for bazel projects? + pkgList = await getMvnMetadata(pkgList, jarNSMapping); + return buildBomNSData(options, pkgList, "maven", { + src: path, + filename: "BUILD", + nsMapping: {}, + dependencies, + parentComponent, + }); } } + } - // scala sbt - // Identify sbt projects via its `project` directory: - // - all SBT project _should_ define build.properties file with sbt version info - // - SBT projects _typically_ have some configs/plugins defined in .sbt files - // - SBT projects that are still on 0.13.x, can still use the old approach, - // where configs are defined via Scala files - // Detecting one of those should be enough to determine an SBT project. - let sbtProjectFiles = getAllFiles( + // scala sbt + // Identify sbt projects via its `project` directory: + // - all SBT project _should_ define build.properties file with sbt version info + // - SBT projects _typically_ have some configs/plugins defined in .sbt files + // - SBT projects that are still on 0.13.x, can still use the old approach, + // where configs are defined via Scala files + // Detecting one of those should be enough to determine an SBT project. + let sbtProjectFiles = getAllFiles( + path, + `${ + options.multiProject ? "**/" : "" + }project/{build.properties,*.sbt,*.scala}`, + options, + ); + + let sbtProjects = []; + for (const i in sbtProjectFiles) { + // parent dir of sbtProjectFile is the `project` directory + // parent dir of `project` is the sbt root project directory + const baseDir = dirname(dirname(sbtProjectFiles[i])); + sbtProjects = sbtProjects.concat(baseDir); + } + + // Fallback in case sbt's project directory is non-existent + if (!sbtProjects.length) { + sbtProjectFiles = getAllFiles( path, - `${ - options.multiProject ? "**/" : "" - }project/{build.properties,*.sbt,*.scala}`, + `${options.multiProject ? "**/" : ""}*.sbt`, options, ); - - let sbtProjects = []; for (const i in sbtProjectFiles) { - // parent dir of sbtProjectFile is the `project` directory - // parent dir of `project` is the sbt root project directory - const baseDir = dirname(dirname(sbtProjectFiles[i])); + const baseDir = dirname(sbtProjectFiles[i]); sbtProjects = sbtProjects.concat(baseDir); } + } + // eliminate duplicates and ignore project directories + sbtProjects = [...new Set(sbtProjects)].filter( + (p) => !p.endsWith(`${sep}project`) && !p.includes(`target${sep}`), + ); + const sbtLockFiles = getAllFiles( + path, + `${options.multiProject ? "**/" : ""}build.sbt.lock`, + options, + ); - // Fallback in case sbt's project directory is non-existent - if (!sbtProjects.length) { - sbtProjectFiles = getAllFiles( - path, - `${options.multiProject ? "**/" : ""}*.sbt`, - options, - ); - for (const i in sbtProjectFiles) { - const baseDir = dirname(sbtProjectFiles[i]); - sbtProjects = sbtProjects.concat(baseDir); - } - } - // eliminate duplicates and ignore project directories - sbtProjects = [...new Set(sbtProjects)].filter( - (p) => !p.endsWith(`${sep}project`) && !p.includes(`target${sep}`), - ); - const sbtLockFiles = getAllFiles( - path, - `${options.multiProject ? "**/" : ""}build.sbt.lock`, - options, - ); - - if (sbtProjects?.length) { - let pkgList = []; - // If the project use sbt lock files - if (sbtLockFiles?.length) { - for (const f of sbtLockFiles) { - const dlist = parseSbtLock(f); - if (dlist?.length) { - pkgList = pkgList.concat(dlist); - } + if (sbtProjects?.length) { + let pkgList = []; + // If the project use sbt lock files + if (sbtLockFiles?.length) { + for (const f of sbtLockFiles) { + const dlist = parseSbtLock(f); + if (dlist?.length) { + pkgList = pkgList.concat(dlist); } - } else { - const SBT_CMD = process.env.SBT_CMD || "sbt"; - let sbtVersion = determineSbtVersion(path); - // If can't find sbt version at the root of repository then search in - // sbt project array too because sometimes the project folder isn't at - // root of repository - if (sbtVersion == null) { - for (const i in sbtProjects) { - sbtVersion = determineSbtVersion(sbtProjects[i]); - if (sbtVersion != null) { - break; - } + } + } else { + const SBT_CMD = process.env.SBT_CMD || "sbt"; + let sbtVersion = determineSbtVersion(path); + // If can't find sbt version at the root of repository then search in + // sbt project array too because sometimes the project folder isn't at + // root of repository + if (sbtVersion == null) { + for (const i in sbtProjects) { + sbtVersion = determineSbtVersion(sbtProjects[i]); + if (sbtVersion != null) { + break; } } - if (DEBUG_MODE) { - console.log(`Detected sbt version: ${sbtVersion}`); - } - // Introduced in 1.2.0 https://www.scala-sbt.org/1.x/docs/sbt-1.2-Release-Notes.html#addPluginSbtFile+command, - // however working properly for real only since 1.3.4: https://github.com/sbt/sbt/releases/tag/v1.3.4 - const standalonePluginFile = - sbtVersion != null && - gte(sbtVersion, "1.3.4") && - lte(sbtVersion, "1.4.0"); - const useSlashSyntax = gte(sbtVersion, "1.5.0"); - const isDependencyTreeBuiltIn = - sbtVersion != null && gte(sbtVersion, "1.4.0"); - const tempDir = mkdtempSync(join(tmpdir(), "cdxsbt-")); - const tempSbtgDir = mkdtempSync(join(tmpdir(), "cdxsbtg-")); - mkdirSync(tempSbtgDir, { recursive: true }); - // Create temporary plugins file - const tempSbtPlugins = join(tempSbtgDir, "dep-plugins.sbt"); + } + if (DEBUG_MODE) { + console.log(`Detected sbt version: ${sbtVersion}`); + } + // Introduced in 1.2.0 https://www.scala-sbt.org/1.x/docs/sbt-1.2-Release-Notes.html#addPluginSbtFile+command, + // however working properly for real only since 1.3.4: https://github.com/sbt/sbt/releases/tag/v1.3.4 + const standalonePluginFile = + sbtVersion != null && + gte(sbtVersion, "1.3.4") && + lte(sbtVersion, "1.4.0"); + const useSlashSyntax = gte(sbtVersion, "1.5.0"); + const isDependencyTreeBuiltIn = + sbtVersion != null && gte(sbtVersion, "1.4.0"); + const tempDir = mkdtempSync(join(tmpdir(), "cdxsbt-")); + const tempSbtgDir = mkdtempSync(join(tmpdir(), "cdxsbtg-")); + mkdirSync(tempSbtgDir, { recursive: true }); + // Create temporary plugins file + const tempSbtPlugins = join(tempSbtgDir, "dep-plugins.sbt"); - // Requires a custom version of `sbt-dependency-graph` that - // supports `--append` for `toFile` subtask. - let sbtPluginDefinition = `\naddSbtPlugin("io.shiftleft" % "sbt-dependency-graph" % "0.10.0-append-to-file3")\n`; - if (isDependencyTreeBuiltIn) { - sbtPluginDefinition = `\naddDependencyTreePlugin\n`; - if (DEBUG_MODE) { - console.log("Using addDependencyTreePlugin as the custom plugin"); - } + // Requires a custom version of `sbt-dependency-graph` that + // supports `--append` for `toFile` subtask. + let sbtPluginDefinition = `\naddSbtPlugin("io.shiftleft" % "sbt-dependency-graph" % "0.10.0-append-to-file3")\n`; + if (isDependencyTreeBuiltIn) { + sbtPluginDefinition = `\naddDependencyTreePlugin\n`; + if (DEBUG_MODE) { + console.log("Using addDependencyTreePlugin as the custom plugin"); } - writeFileSync(tempSbtPlugins, sbtPluginDefinition); - for (const i in sbtProjects) { - const basePath = sbtProjects[i]; - const dlFile = join(tempDir, `dl-${i}.tmp`); - let sbtArgs = []; - let pluginFile = null; - if (standalonePluginFile) { + } + writeFileSync(tempSbtPlugins, sbtPluginDefinition); + for (const i in sbtProjects) { + const basePath = sbtProjects[i]; + const dlFile = join(tempDir, `dl-${i}.tmp`); + let sbtArgs = []; + let pluginFile = null; + if (standalonePluginFile) { + sbtArgs = [ + `-addPluginSbtFile=${tempSbtPlugins}`, + `"dependencyList::toFile ${dlFile} --force"`, + ]; + } else { + // write to the existing plugins file + if (useSlashSyntax) { sbtArgs = [ - `-addPluginSbtFile=${tempSbtPlugins}`, - `"dependencyList::toFile ${dlFile} --force"`, + `'set ThisBuild / asciiGraphWidth := 400' "dependencyTree / toFile ${dlFile} --force"`, ]; } else { - // write to the existing plugins file - if (useSlashSyntax) { - sbtArgs = [ - `'set ThisBuild / asciiGraphWidth := 400' "dependencyTree / toFile ${dlFile} --force"`, - ]; - } else { - sbtArgs = [ - `'set asciiGraphWidth in ThisBuild := 400' "dependencyTree::toFile ${dlFile} --force"`, - ]; - } - pluginFile = addPlugin(basePath, sbtPluginDefinition); + sbtArgs = [ + `'set asciiGraphWidth in ThisBuild := 400' "dependencyTree::toFile ${dlFile} --force"`, + ]; } + pluginFile = addPlugin(basePath, sbtPluginDefinition); + } + console.log( + "Executing", + SBT_CMD, + sbtArgs.join(" "), + "in", + basePath, + "using plugins", + tempSbtgDir, + ); + // Note that the command has to be invoked with `shell: true` to properly execut sbt + const result = spawnSync(SBT_CMD, sbtArgs, { + cwd: basePath, + shell: true, + encoding: "utf-8", + timeout: TIMEOUT_MS, + maxBuffer: MAX_BUFFER, + }); + if (result.status !== 0 || result.error) { + console.error(result.stdout, result.stderr); console.log( - "Executing", - SBT_CMD, - sbtArgs.join(" "), - "in", - basePath, - "using plugins", - tempSbtgDir, + `1. Check if scala and sbt is installed and available in PATH. Only scala 2.10 + sbt 0.13.6+ and 2.12 + sbt 1.0+ is supported for now.`, ); - // Note that the command has to be invoked with `shell: true` to properly execut sbt - const result = spawnSync(SBT_CMD, sbtArgs, { - cwd: basePath, - shell: true, - encoding: "utf-8", - timeout: TIMEOUT_MS, - maxBuffer: MAX_BUFFER, - }); - if (result.status !== 0 || result.error) { - console.error(result.stdout, result.stderr); - console.log( - `1. Check if scala and sbt is installed and available in PATH. Only scala 2.10 + sbt 0.13.6+ and 2.12 + sbt 1.0+ is supported for now.`, - ); - console.log( - `2. Check if the plugin net.virtual-void:sbt-dependency-graph 0.10.0-RC1 can be used in the environment`, - ); - console.log( - "3. Consider creating a lockfile using sbt-dependency-lock plugin. See https://github.com/stringbean/sbt-dependency-lock", - ); - options.failOnError && process.exit(1); + console.log( + `2. Check if the plugin net.virtual-void:sbt-dependency-graph 0.10.0-RC1 can be used in the environment`, + ); + console.log( + "3. Consider creating a lockfile using sbt-dependency-lock plugin. See https://github.com/stringbean/sbt-dependency-lock", + ); + options.failOnError && process.exit(1); + } + if (!standalonePluginFile) { + cleanupPlugin(basePath, pluginFile); + } + if (existsSync(dlFile)) { + const retMap = parseSbtTree(dlFile); + if (retMap.pkgList?.length) { + const tmpParentComponent = retMap.pkgList.splice(0, 1)[0]; + tmpParentComponent.type = "application"; + pkgList = pkgList.concat(retMap.pkgList); + if (!parentComponent || !Object.keys(parentComponent).length) { + parentComponent = tmpParentComponent; + } } - if (!standalonePluginFile) { - cleanupPlugin(basePath, pluginFile); + if (retMap.dependenciesList) { + dependencies = mergeDependencies( + dependencies, + retMap.dependenciesList, + parentComponent, + ); } - if (existsSync(dlFile)) { - const retMap = parseSbtTree(dlFile); - if (retMap.pkgList?.length) { - const tmpParentComponent = retMap.pkgList.splice(0, 1)[0]; - tmpParentComponent.type = "application"; - pkgList = pkgList.concat(retMap.pkgList); - if (!parentComponent || !Object.keys(parentComponent).length) { - parentComponent = tmpParentComponent; - } - } - if (retMap.dependenciesList) { - dependencies = mergeDependencies( - dependencies, - retMap.dependenciesList, - parentComponent, - ); - } - } else { - if (options.failOnError || DEBUG_MODE) { - console.log(`sbt dependencyList did not yield ${dlFile}`); - } - options.failOnError && process.exit(1); + } else { + if (options.failOnError || DEBUG_MODE) { + console.log(`sbt dependencyList did not yield ${dlFile}`); } + options.failOnError && process.exit(1); } + } - // Cleanup - unlinkSync(tempSbtPlugins); - } // else + // Cleanup + unlinkSync(tempSbtPlugins); + } // else - if (DEBUG_MODE) { - console.log(`Found ${pkgList.length} packages`); - } - // Should we attempt to resolve class names - if (options.resolveClass || options.deep) { - const tmpjarNSMapping = await collectJarNS(SBT_CACHE_DIR); - if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) { - jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping }; - } + if (DEBUG_MODE) { + console.log(`Found ${pkgList.length} packages`); + } + // Should we attempt to resolve class names + if (options.resolveClass || options.deep) { + const tmpjarNSMapping = await collectJarNS(SBT_CACHE_DIR); + if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) { + jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping }; } - pkgList = await getMvnMetadata(pkgList, jarNSMapping); - return buildBomNSData(options, pkgList, "maven", { - src: path, - filename: sbtProjects.join(", "), - nsMapping: jarNSMapping, - dependencies, - parentComponent, - }); } + pkgList = await getMvnMetadata(pkgList, jarNSMapping); + return buildBomNSData(options, pkgList, "maven", { + src: path, + filename: sbtProjects.join(", "), + nsMapping: jarNSMapping, + dependencies, + parentComponent, + }); } } @@ -2150,7 +2126,8 @@ export async function createNodejsBom(path, options) { src: path, filename: "shrinkwrap-deps.json", }); - } else if (existsSync(pnpmLock)) { + } + if (existsSync(pnpmLock)) { let pkgList = await parsePnpmLock(pnpmLock); if (allImports && Object.keys(allImports).length) { pkgList = await addEvidenceForImports( @@ -2166,16 +2143,15 @@ export async function createNodejsBom(path, options) { src: path, filename: "pnpm-lock.yaml", }); - } else { - console.log( - "Neither shrinkwrap file: ", - swFile, - " nor pnpm lockfile", - pnpmLock, - "was found!", - ); - options.failOnError && process.exit(1); } + console.log( + "Neither shrinkwrap file: ", + swFile, + " nor pnpm lockfile", + pnpmLock, + "was found!", + ); + options.failOnError && process.exit(1); } if (yarnLockFiles?.length) { manifestFiles = manifestFiles.concat(yarnLockFiles); @@ -2458,7 +2434,8 @@ export async function createPythonBom(path, options) { dependencies, parentComponent, }); - } else if (metadataFiles?.length) { + } + if (metadataFiles?.length) { // dist-info directories for (const mf of metadataFiles) { const mData = readFileSync(mf, { @@ -2970,7 +2947,8 @@ export async function createGoBom(path, options) { parentComponent, filename: gomodFiles.join(", "), }); - } else if (gopkgLockFiles.length) { + } + if (gopkgLockFiles.length) { for (const f of gopkgLockFiles) { if (DEBUG_MODE) { console.log(`Parsing ${f}`); @@ -3144,7 +3122,8 @@ export async function createDartBom(path, options) { src: path, filename: pubFiles.join(", "), }); - } else if (pubSpecYamlFiles.length) { + } + if (pubSpecYamlFiles.length) { for (const f of pubSpecYamlFiles) { if (DEBUG_MODE) { console.log(`Parsing ${f}`); @@ -3413,7 +3392,8 @@ export function createClojureBom(path, options) { src: path, filename: leinFiles.join(", "), }); - } else if (ednFiles.length) { + } + if (ednFiles.length) { let CLJ_ARGS = ["-Stree"]; if (process.env.CLJ_ARGS) { CLJ_ARGS = process.env.CLJ_ARGS.split(" "); @@ -5836,9 +5816,8 @@ export async function createBom(path, options) { // https://github.com/cyclonedx/cdxgen/issues/95 if (options.multiProject) { return await createMultiXBom([path], options); - } else { - return await createXBom(path, options); } + return await createXBom(path, options); } } diff --git a/utils.js b/utils.js index 46b0d4cef..618710294 100644 --- a/utils.js +++ b/utils.js @@ -328,15 +328,13 @@ export function adjustLicenseInformation(licenses) { console.warn("multiple license expressions found", expressions); } return [{ expression: expressions[0].expression }]; - } else { - return licenses.map((l) => { - if (typeof l.license === "object") { - return l; - } else { - return { license: l }; - } - }); } + return licenses.map((l) => { + if (typeof l.license === "object") { + return l; + } + return { license: l }; + }); } /** @@ -390,11 +388,10 @@ export function getLicenses(pkg) { return licenseContent; }), ); - } else { - const knownLicense = getKnownLicense(undefined, pkg); - if (knownLicense) { - return [{ license: knownLicense }]; - } + } + const knownLicense = getKnownLicense(undefined, pkg); + if (knownLicense) { + return [{ license: knownLicense }]; } return undefined; } @@ -438,7 +435,8 @@ export function getKnownLicense(licenseUrl, pkg) { if (akLic.group && akLic.name) { if (akLic.group === "." && akLic.name === pkg.name) { return { id: akLic.license, name: akLic.licenseName }; - } else if ( + } + if ( pkg.group?.includes(akLic.group) && (akLic.name === pkg.name || akLic.name === "*") ) { @@ -2312,12 +2310,11 @@ export function executeGradleProperties(dir, rootPath, subProject) { if (result.stderr) { if (result.stderr.includes("does not exist")) { return defaultProps; - } else { - console.error(result.stdout, result.stderr); - console.log( - "1. Check if the correct version of java and gradle are installed and available in PATH. For example, some project might require Java 11 with gradle 7.\n cdxgen container image bundles Java 21 with gradle 8 which might be incompatible.", - ); } + console.error(result.stdout, result.stderr); + console.log( + "1. Check if the correct version of java and gradle are installed and available in PATH. For example, some project might require Java 11 with gradle 7.\n cdxgen container image bundles Java 21 with gradle 8 which might be incompatible.", + ); if (result.stderr.includes("not get unknown property")) { console.log( "2. Check if the SBOM is generated for the correct root project for your application.", @@ -2719,7 +2716,8 @@ export function parseLicenseEntryOrArrayFromPomXml(license) { return license.map((l) => { return findLicenseId(l.name._); }); - } else if (Object.keys(license).length) { + } + if (Object.keys(license).length) { return [findLicenseId(license.name._)]; } } @@ -2762,7 +2760,8 @@ export function parsePyRequiresDist(dist_string) { let version = ""; if (!tmpA) { return undefined; - } else if (tmpA.length == 1) { + } + if (tmpA.length == 1) { name = tmpA[0]; } else if (tmpA.length > 1) { name = tmpA[0]; @@ -3514,9 +3513,8 @@ export function repoMetadataToGitHubApiUrl(repoMetadata) { } ghUrl = `${ghUrl}/${name}`; return ghUrl; - } else { - return undefined; } + return undefined; } /** @@ -3546,12 +3544,11 @@ export function toGitHubApiUrl(repoUrl, repoMetadata) { const parts = getGithubUrlParts(repoUrl); if (parts.length < 5 || parts[2] !== "github.com") { return undefined; // Not a valid GitHub repo URL - } else { - return repoMetadataToGitHubApiUrl({ - group: parts[3], - name: parts[4], - }); } + return repoMetadataToGitHubApiUrl({ + group: parts[3], + name: parts[4], + }); } /** @@ -3731,10 +3728,12 @@ export async function parseGoModData(goModData, gosumMap) { if (l.includes("require (")) { isModReplacement = false; continue; - } else if (l.includes("replace (")) { + } + if (l.includes("replace (")) { isModReplacement = true; continue; - } else if (l.includes("replace ")) { + } + if (l.includes("replace ")) { // If this is an inline replacement, drop the word replace // (eg; "replace google.golang.org/grpc => google.golang.org/grpc v1.21.0" becomes " google.golang.org/grpc => google.golang.org/grpc v1.21.0") l = l.replace("replace", ""); @@ -4265,9 +4264,8 @@ export async function parseGemspecData(gemspecData) { pkgList = [pkg]; if (FETCH_LICENSE) { return await getRubyGemsMetadata(pkgList); - } else { - return pkgList; } + return pkgList; } /** @@ -4807,9 +4805,8 @@ export async function parseCargoTomlData(cargoTomlFile, simple = false) { } if (!simple && FETCH_LICENSE) { return await getCratesMetadata(pkgList); - } else { - return pkgList; } + return pkgList; } /** @@ -4938,9 +4935,8 @@ export async function parseCargoData(cargoLockFile, simple = false) { } if (FETCH_LICENSE && !simple) { return await getCratesMetadata(pkgList); - } else { - return pkgList; } + return pkgList; } export function parseCargoDependencyData(cargoLockData) { @@ -5105,9 +5101,8 @@ export async function parseCargoAuditableData(cargoData) { }); if (FETCH_LICENSE) { return await getCratesMetadata(pkgList); - } else { - return pkgList; } + return pkgList; } export async function parsePubLockData(pubLockData) { @@ -5145,9 +5140,8 @@ export async function parsePubLockData(pubLockData) { }); if (FETCH_LICENSE) { return await getDartMetadata(pkgList); - } else { - return pkgList; } + return pkgList; } export function parsePubYamlData(pubYamlData) { @@ -5375,16 +5369,15 @@ export function parseBitbucketPipelinesFile(fileContents) { if (imageName === "") { privateImageBlockFound = true; continue; - } else { - /** - * Assume this is a public build image - * See: https://support.atlassian.com/bitbucket-cloud/docs/use-docker-images-as-build-environments/#Using-public-build-images - */ - - imgList.push({ - image: imageName, - }); } + /** + * Assume this is a public build image + * See: https://support.atlassian.com/bitbucket-cloud/docs/use-docker-images-as-build-environments/#Using-public-build-images + */ + + imgList.push({ + image: imageName, + }); } // Pipe usage @@ -6141,9 +6134,8 @@ export function parseCsProjAssetsData(csProjData, assetsJsonFile) { operator: match[2], version: match[3], }; - } else { - return null; } + return null; } const pkgList = []; @@ -8139,19 +8131,13 @@ export function cleanupPlugin(projectPath, originalPluginsFile) { // just remove the file, it was never there unlinkSync(pluginsFile); return !existsSync(pluginsFile); - } else { - // Bring back the original file - copyFileSync( - originalPluginsFile, - pluginsFile, - constants.COPYFILE_FICLONE, - ); - unlinkSync(originalPluginsFile); - return true; } - } else { - return false; + // Bring back the original file + copyFileSync(originalPluginsFile, pluginsFile, constants.COPYFILE_FICLONE); + unlinkSync(originalPluginsFile); + return true; } + return false; } /** @@ -9795,24 +9781,24 @@ async function queryNuget(p, NUGET_URL) { Number(tmpVersionArray.slice(-1)) === 0 ) { return upper; - } else if (upper.split("-").length > 1) { + } + if (upper.split("-").length > 1) { tmpVersionArray[tmpVersionArray.length - 1] = ( Number(tmpVersionArray.slice(-1)) - 1 ).toString(); } return tmpVersionArray.join("."); - } else { - const tmpVersion = parse(upper); - let version = `${tmpVersion.major}.${tmpVersion.minor}.${tmpVersion.patch}`; - if (compare(version, upper) === 1) { - if (tmpVersion.patch > 0) { - version = `${tmpVersion.major}.${tmpVersion.minor}.${( - tmpVersion.patch - 1 - ).toString()}`; - } + } + const tmpVersion = parse(upper); + let version = `${tmpVersion.major}.${tmpVersion.minor}.${tmpVersion.patch}`; + if (compare(version, upper) === 1) { + if (tmpVersion.patch > 0) { + version = `${tmpVersion.major}.${tmpVersion.minor}.${( + tmpVersion.patch - 1 + ).toString()}`; } - return version; } + return version; } // Coerce only when missing patch/minor version function coerceUp(version) {