Skip to content

Commit

Permalink
fix: handle spaces in package manager binaries paths
Browse files Browse the repository at this point in the history
Signed-off-by: Zvi Grinberg <[email protected]>
  • Loading branch information
zvigrinberg committed Jun 13, 2024
1 parent 998f96c commit aa67a1c
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 30 deletions.
10 changes: 5 additions & 5 deletions src/providers/golang_gomodules.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { execSync } from "node:child_process"
import fs from 'node:fs'
import os from "node:os";
import {EOL} from "os";

Check warning on line 5 in src/providers/golang_gomodules.js

View workflow job for this annotation

GitHub Actions / Lint and test project (18)

Imports should be sorted alphabetically

Check warning on line 5 in src/providers/golang_gomodules.js

View workflow job for this annotation

GitHub Actions / Lint and test project (latest)

Imports should be sorted alphabetically
import {getCustom, getCustomPath} from "../tools.js";
import {getCustom, getCustomPath, handleSpacesInPath} from "../tools.js";
import path from 'node:path'
import Sbom from '../sbom.js'
import {PackageURL} from 'packageurl-js'
Expand Down Expand Up @@ -72,7 +72,7 @@ function provideComponent(data, opts = {}) {


function getGoGraphCommand(goBin) {
return `${goBin} mod graph `;
return `${handleSpacesInPath(goBin)} mod graph `;
}

/**
Expand Down Expand Up @@ -273,7 +273,7 @@ function getSBOM(manifest, opts = {}, includeTransitive) {
// get custom goBin path
let goBin = getCustomPath('go', opts)
// verify goBin is accessible
execSync(`${goBin} version`, err => {
execSync(`${handleSpacesInPath(goBin)} version`, err => {
if (err) {
throw new Error('go binary is not accessible')
}
Expand Down Expand Up @@ -380,8 +380,8 @@ function toPurl(dependency, delimiter, qualifiers) {
function getFinalPackagesVersionsForModule(rows,manifestPath,goBin) {
let manifestDir = path.dirname(manifestPath)
let options = {cwd: manifestDir}
execSync(`${goBin} mod download`, options)
let finalVersionsForAllModules = execSync(`${goBin} list -m all`, options).toString()
execSync(`${handleSpacesInPath(goBin)} mod download`, options)
let finalVersionsForAllModules = execSync(`${handleSpacesInPath(goBin)} list -m all`, options).toString()
let finalVersionModules = new Map()
finalVersionsForAllModules.split(EOL).filter(string => string.trim()!== "")
.filter(string => string.trim().split(" ").length === 2)
Expand Down
6 changes: 3 additions & 3 deletions src/providers/java_gradle.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fs from 'node:fs'
import {getCustomPath} from "../tools.js";
import {getCustomPath, handleSpacesInPath} from "../tools.js";
import path from 'node:path'
import Sbom from '../sbom.js'
import {EOL} from 'os'
Expand Down Expand Up @@ -176,7 +176,7 @@ export default class Java_gradle extends Base_java {
let gradle = getCustomPath("gradle", opts);
let properties
try {
properties = this._invokeCommandGetOutput(`${gradle} properties`, path.dirname(manifestPath))
properties = this._invokeCommandGetOutput(`${handleSpacesInPath(gradle)} properties`, path.dirname(manifestPath))
} catch (e) {
throw new Error(`Couldn't get properties of build.gradle file , Error message returned from gradle binary => ${EOL} ${e.getMessage}`)
}
Expand Down Expand Up @@ -221,7 +221,7 @@ export default class Java_gradle extends Base_java {
let commandResult
gradle = getCustomPath("gradle")
try {
commandResult = this._invokeCommandGetOutput(`${gradle} dependencies`,path.dirname(manifest))
commandResult = this._invokeCommandGetOutput(`${handleSpacesInPath(gradle)} dependencies`,path.dirname(manifest))
} catch (e) {
throw new Error(`Couldn't run gradle dependencies command, error message returned from gradle binary => ${EOL} ${e.getMessage}`)
}
Expand Down
10 changes: 5 additions & 5 deletions src/providers/java_maven.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,14 @@ export default class Java_maven extends Base_java {
// get custom maven path
let mvn = getCustomPath('mvn', opts)
// verify maven is accessible
this._invokeCommand(`${mvn} --version`,'mvn is not accessible')
this._invokeCommand(`${handleSpacesInPath(mvn)} --version`,'mvn is not accessible')
// clean maven target
this._invokeCommand(`${mvn} -q clean -f ${handleSpacesInPath(manifest)}`,'failed cleaning maven target')
this._invokeCommand(`${handleSpacesInPath(mvn)} -q clean -f ${handleSpacesInPath(manifest)}`,'failed cleaning maven target')
// create dependency graph in a temp file
let tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'exhort_'))
let tmpDepTree = path.join(tmpDir, 'mvn_deptree.txt')
// build initial command (dot outputType is not available for verbose mode)
let depTreeCmd = `${mvn} -q org.apache.maven.plugins:maven-dependency-plugin:3.6.0:tree -Dverbose -DoutputType=text -DoutputFile=${handleSpacesInPath(tmpDepTree)} -f ${handleSpacesInPath(manifest)}`
let depTreeCmd = `${handleSpacesInPath(mvn)} -q org.apache.maven.plugins:maven-dependency-plugin:3.6.0:tree -Dverbose -DoutputType=text -DoutputFile=${handleSpacesInPath(tmpDepTree)} -f ${handleSpacesInPath(manifest)}`
// exclude ignored dependencies, exclude format is groupId:artifactId:scope:version.
// version and scope are marked as '*' if not specified (we do not use scope yet)
let ignoredDeps = new Array()
Expand Down Expand Up @@ -132,7 +132,7 @@ export default class Java_maven extends Base_java {
// get custom maven path
let mvn = getCustomPath('mvn', opts)
// verify maven is accessible
this._invokeCommand(`${mvn} --version`,'mvn is not accessible')
this._invokeCommand(`${handleSpacesInPath(mvn)} --version`,'mvn is not accessible')
// create temp files for pom and effective pom
let tmpDir
let tmpEffectivePom
Expand All @@ -150,7 +150,7 @@ export default class Java_maven extends Base_java {
}

// create effective pom and save to temp file
this._invokeCommand(`${mvn} -q help:effective-pom -Doutput=${handleSpacesInPath(tmpEffectivePom)} -f ${handleSpacesInPath(targetPom)}`,'failed creating maven effective pom')
this._invokeCommand(`${handleSpacesInPath(mvn)} -q help:effective-pom -Doutput=${handleSpacesInPath(tmpEffectivePom)} -f ${handleSpacesInPath(targetPom)}`,'failed creating maven effective pom')
// iterate over all dependencies in original pom and collect all ignored ones
let ignored = this.#getDependencies(targetPom).filter(d => d.ignore)
// iterate over all dependencies and create a package for every non-ignored one
Expand Down
6 changes: 3 additions & 3 deletions src/providers/javascript_npm.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ export var npmInteractions = {
return npmOutput;
},
version: function checkNpmVersion(npm) {
execSync(`${npm} --version`, err => {
execSync(`${handleSpacesInPath(npm)} --version`, err => {
if (err) {
throw new Error('npm is not accessible')
}
})
},
createPackageLock: function createPackageLock(npm, manifestDir) {
execSync(`${npm} i --package-lock-only --prefix ${handleSpacesInPath(manifestDir)}`, err => {
execSync(`${handleSpacesInPath(npm)} i --package-lock-only --prefix ${handleSpacesInPath(manifestDir)}`, err => {
if (err) {
throw new Error('failed to create npmOutput list')
}
Expand Down Expand Up @@ -109,7 +109,7 @@ function provideComponent(data, opts = {}, path = '') {
* @return {string} returns a string containing the result output.
*/
function getNpmListing(npm, allFilter, manifestDir) {
return `${npm} ls${allFilter} --omit=dev --package-lock-only --json --prefix ${manifestDir}`;
return `${handleSpacesInPath(npm)} ls${allFilter} --omit=dev --package-lock-only --json --prefix ${manifestDir}`;
}


Expand Down
18 changes: 9 additions & 9 deletions src/providers/python_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {environmentVariableIsPopulated,getCustom, handleSpacesInPath} from "../t


function getPipFreezeOutput() {
return environmentVariableIsPopulated("EXHORT_PIP_FREEZE") ? new Buffer(process.env["EXHORT_PIP_FREEZE"],'base64').toString('ascii') : execSync(`${this.pathToPipBin} freeze --all`, err => {
return environmentVariableIsPopulated("EXHORT_PIP_FREEZE") ? new Buffer(process.env["EXHORT_PIP_FREEZE"],'base64').toString('ascii') : execSync(`${handleSpacesInPath(this.pathToPipBin)} freeze --all`, err => {
if (err) {
throw new Error('fail invoking pip freeze to fetch all installed dependencies in environment --> ' + err.message)
}
Expand All @@ -15,7 +15,7 @@ function getPipFreezeOutput() {

function getPipShowOutput(depNames) {

return environmentVariableIsPopulated("EXHORT_PIP_SHOW") ? new Buffer(process.env["EXHORT_PIP_SHOW"],'base64').toString('ascii') : execSync(`${this.pathToPipBin} show ${depNames}`, err => {
return environmentVariableIsPopulated("EXHORT_PIP_SHOW") ? new Buffer(process.env["EXHORT_PIP_SHOW"],'base64').toString('ascii') : execSync(`${handleSpacesInPath(this.pathToPipBin)} show ${depNames}`, err => {
if (err) {
throw new Error('fail invoking pip show to fetch all installed dependencies metadata --> ' + err.message)
}
Expand Down Expand Up @@ -55,7 +55,7 @@ export default class Python_controller {
{
if(!this.realEnvironment) {
this.pythonEnvDir = path.join(path.sep,"tmp","exhort_env_js")
execSync(`${this.pathToPythonBin} -m venv ${this.pythonEnvDir} `, err => {
execSync(`${handleSpacesInPath(this.pathToPythonBin)} -m venv ${this.pythonEnvDir} `, err => {
if (err) {
throw new Error('failed creating virtual python environment - ' + err.message)
}
Expand All @@ -70,7 +70,7 @@ export default class Python_controller {
this.pathToPythonBin = path.join(this.pythonEnvDir,"bin","python")
}
// upgrade pip version to latest
execSync(`${this.pathToPythonBin} -m pip install --upgrade pip `, err => {
execSync(`${handleSpacesInPath(this.pathToPythonBin)} -m pip install --upgrade pip `, err => {
if (err) {
throw new Error('failed upgrading pip version on virtual python environment - ' + err.message)
}
Expand Down Expand Up @@ -104,7 +104,7 @@ export default class Python_controller {
let installBestEfforts = getCustom("EXHORT_PYTHON_INSTALL_BEST_EFFORTS","false",this.options);
if(installBestEfforts === "false")
{
execSync(`${this.pathToPipBin} install -r ${handleSpacesInPath(this.pathToRequirements)}`, err =>{
execSync(`${handleSpacesInPath(this.pathToPipBin)} install -r ${handleSpacesInPath(this.pathToRequirements)}`, err =>{
if (err) {
throw new Error('fail installing requirements.txt manifest in created virtual python environment --> ' + err.message)
}
Expand Down Expand Up @@ -138,7 +138,7 @@ export default class Python_controller {
let requirementsRows = requirementsContent.toString().split(EOL);
requirementsRows.filter((line) => !line.trim().startsWith("#")).filter((line) => line.trim() !== "").forEach( (dependency) => {
let dependencyName = getDependencyName(dependency);
execSync(`${this.pathToPipBin} install ${dependencyName}`, err =>{
execSync(`${handleSpacesInPath(this.pathToPipBin)} install ${dependencyName}`, err =>{
if (err) {
throw new Error(`Best efforts process - failed installing ${dependencyName} in created virtual python environment --> error message: ` + err.message)
}
Expand All @@ -152,7 +152,7 @@ export default class Python_controller {
{
if(!this.realEnvironment)
{
execSync(`${this.pathToPipBin} uninstall -y -r ${handleSpacesInPath(this.pathToRequirements)}`, err =>{
execSync(`${handleSpacesInPath(this.pathToPipBin)} uninstall -y -r ${handleSpacesInPath(this.pathToRequirements)}`, err =>{
if (err) {
throw new Error('fail uninstalling requirements.txt in created virtual python environment --> ' + err.message)
}
Expand Down Expand Up @@ -400,7 +400,7 @@ function bringAllDependencies(dependencies, dependencyName, cachedEnvironmentDep
function getDependencyTreeJsonFromPipDepTree(pipPath,pythonPath) {
let dependencyTree
try {
execSync(`${pipPath} install pipdeptree`)
execSync(`${handleSpacesInPath(pipPath)} install pipdeptree`)
} catch (e) {
throw new Error(`Couldn't install pipdeptree utility, reason: ${e.getMessage}`)
}
Expand All @@ -410,7 +410,7 @@ function getDependencyTreeJsonFromPipDepTree(pipPath,pythonPath) {
dependencyTree = execSync(`pipdeptree --json`).toString()
}
else {
dependencyTree = execSync(`pipdeptree --json --python ${pythonPath} `).toString()
dependencyTree = execSync(`pipdeptree --json --python ${handleSpacesInPath(pythonPath)} `).toString()
}
} catch (e) {
throw new Error(`couldn't produce dependency tree using pipdeptree tool, stop analysis, message -> ${e.getMessage}`)
Expand Down
15 changes: 10 additions & 5 deletions src/providers/python_pip.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@

import {execSync} from "node:child_process";
import fs from 'node:fs'
import {environmentVariableIsPopulated, getCustom,getCustomPath } from "../tools.js";
import {
environmentVariableIsPopulated,
getCustom,
getCustomPath,
handleSpacesInPath
} from "../tools.js";
import os from 'node:os'
import path from 'node:path'
import Sbom from '../sbom.js'
Expand Down Expand Up @@ -151,14 +156,14 @@ function getPythonPipBinaries(binaries,opts) {
let python = getCustomPath("python3",opts)
let pip = getCustomPath("pip3",opts)
try {
execSync(`${python} --version`)
execSync(`${pip} --version`)
execSync(`${handleSpacesInPath(python)} --version`)
execSync(`${handleSpacesInPath(pip)} --version`)
} catch (e) {
python = getCustomPath("python",opts)
pip = getCustomPath("pip",opts)
try {
execSync(`${python} --version`)
execSync(`${pip} --version`)
execSync(`${handleSpacesInPath(python)} --version`)
execSync(`${handleSpacesInPath(pip)} --version`)
} catch (e) {
throw new Error(`Couldn't get python binaries from supplied environment variables ${e.getMessage}`)
}
Expand Down

0 comments on commit aa67a1c

Please sign in to comment.