Skip to content

Commit

Permalink
fix: pr comments
Browse files Browse the repository at this point in the history
  • Loading branch information
orsagie committed Jul 30, 2019
1 parent 42e8be1 commit fa6acd9
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 138 deletions.
69 changes: 39 additions & 30 deletions lib/nuget-parser/csproj-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,50 @@ import * as _ from 'lodash';
import * as debugModule from 'debug';
const debug = debugModule('snyk');

export async function getTargetFrameworksFromProjFile(rootDir) {
debug('Looking for your .csproj file in ' + rootDir);
const csprojPath = findFile(rootDir, /.*\.csproj$/);
if (csprojPath) {
debug('Checking .net framework version in .csproj file ' + csprojPath);
interface TargetFramework {
framework: string;
original: string;
version: string;
}

const csprojContents = fs.readFileSync(csprojPath);
export async function getTargetFrameworksFromProjFile(rootDir: string): Promise<any> {
return new Promise((resolve, reject) => {
debug('Looking for your .csproj file in ' + rootDir);
const csprojPath = findFile(rootDir, /.*\.csproj$/);
if (csprojPath) {
debug('Checking .net framework version in .csproj file ' + csprojPath);

let frameworks: any = [];
parseXML.parseString(csprojContents, (err, parsedCsprojContents) => {
if (err) {
throw new FileNotProcessableError(err);
}
const versionLoc = _.get(parsedCsprojContents, 'Project.PropertyGroup[0]');
const versions = _.compact(_.concat([],
_.get(versionLoc, 'TargetFrameworkVersion[0]') ||
_.get(versionLoc, 'TargetFramework[0]') ||
_.get(versionLoc, 'TargetFrameworks[0]', '').split(';')));
const csprojContents = fs.readFileSync(csprojPath);

if (versions.length < 1) {
debug('Could not find TargetFrameworkVersion/TargetFramework' +
'/TargetFrameworks defined in the Project.PropertyGroup field of ' +
'your .csproj file');
}
frameworks = _.compact(_.map(versions, toReadableFramework));
if (versions.length > 1 && frameworks.length < 1) {
debug('Could not find valid/supported .NET version in csproj file located at' + csprojPath);
}
});
return frameworks[0];
}
debug('.csproj file not found in ' + rootDir + '.');
let frameworks: TargetFramework[] = [];
parseXML.parseString(csprojContents, (err, parsedCsprojContents) => {
if (err) {
reject(new FileNotProcessableError(err));
}
const versionLoc = _.get(parsedCsprojContents, 'Project.PropertyGroup[0]');
const versions = _.compact(_.concat([],
_.get(versionLoc, 'TargetFrameworkVersion[0]') ||
_.get(versionLoc, 'TargetFramework[0]') ||
_.get(versionLoc, 'TargetFrameworks[0]', '').split(';')));

if (versions.length < 1) {
debug('Could not find TargetFrameworkVersion/TargetFramework' +
'/TargetFrameworks defined in the Project.PropertyGroup field of ' +
'your .csproj file');
}
frameworks = _.compact(_.map(versions, toReadableFramework));
if (versions.length > 1 && frameworks.length < 1) {
debug('Could not find valid/supported .NET version in csproj file located at' + csprojPath);
}
resolve(frameworks[0]);
});
}
debug('.csproj file not found in ' + rootDir + '.');
resolve();
});
}

function toReadableFramework(targetFramework) {
function toReadableFramework(targetFramework: string): TargetFramework | undefined {
const typeMapping = {
net: '.NETFramework',
netcoreapp: '.NETCore',
Expand Down
2 changes: 1 addition & 1 deletion lib/nuget-parser/dependency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function fromFolderName(folderName) {
};
}

export function fromPackgesConfigEntry(manifest) {
export function fromPackagesConfigEntry(manifest) {
debug('Extracting by packages.config entry:' +
' name = ' + manifest.$.id +
' version = ' + manifest.$.version);
Expand Down
78 changes: 39 additions & 39 deletions lib/nuget-parser/dotnet-core-parser.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import {BigTreeError, InvalidManifestError} from '../errors';
import {BigTreeError, FileNotProcessableError, InvalidManifestError} from '../errors';
import * as _ from 'lodash';
import * as debugModule from 'debug';
const debug = debugModule('snyk');

// TODO: any convention for global vars? (gFreqDeps)
const freqDeps: any = {};
interface FreqDepParent {
dependencies: any;
name: 'freqSystemDependencies';
version: number;
}

interface FreqDeps {
[dep: string]: boolean | FreqDepParent;
}
const freqDeps: FreqDeps = {};

function initFreqDepsDict() {
freqDeps['Microsoft.NETCore.Platforms'] = false;
Expand Down Expand Up @@ -137,48 +146,39 @@ function validateManifest(manifest) {
}
}

module.exports = {
parse: (tree, manifest) => {
return new Promise(function parseFileContents(resolve, reject) {
debug('Trying to parse dot-net-cli manifest');
export async function parse (tree, manifest) {
debug('Trying to parse dot-net-cli manifest');

try {
validateManifest(manifest);
} catch (err) {
debug('Invalid project.assets.json manifest file');
reject(err);
}
validateManifest(manifest);

if (manifest.project.version) {
tree.version = manifest.project.version;
}
if (manifest.project.version) {
tree.version = manifest.project.version;
}

// If a targetFramework was not found in the proj file, we will extract it from the lock file
if (!tree.meta.targetFramework) {
tree.meta.targetFramework = getFrameworkToRun(manifest);
}
const selectedFrameworkObj = manifest.project.frameworks[tree.meta.targetFramework];
// If a targetFramework was not found in the proj file, we will extract it from the lock file
if (!tree.meta.targetFramework) {
tree.meta.targetFramework = getFrameworkToRun(manifest);
}
const selectedFrameworkObj = manifest.project.frameworks[tree.meta.targetFramework];

// We currently ignore the found targetFramework when looking for target dependencies
const selectedTargetObj = getTargetObjToRun(manifest);
// We currently ignore the found targetFramework when looking for target dependencies
const selectedTargetObj = getTargetObjToRun(manifest);

initFreqDepsDict();
initFreqDepsDict();

const directDependencies = collectFlatList(selectedFrameworkObj.dependencies);
debug(`directDependencies: '${directDependencies}'`);
const directDependencies = collectFlatList(selectedFrameworkObj.dependencies);
debug(`directDependencies: '${directDependencies}'`);

directDependencies.forEach((directDep) => {
debug(`First order dep: '${directDep}'`);
buildTreeRecursive(selectedTargetObj, directDep, tree, 0);
});
directDependencies.forEach((directDep) => {
debug(`First order dep: '${directDep}'`);
buildTreeRecursive(selectedTargetObj, directDep, tree, 0);
});

if (!_.isEmpty(freqDeps.dependencies.dependencies)) {
tree.dependencies.freqSystemDependencies = freqDeps.dependencies;
}
// to disconnect the object references inside the tree
// JSON parse/stringify is used
tree.dependencies = JSON.parse(JSON.stringify(tree.dependencies));
resolve(tree);
});
},
};
if (!_.isEmpty((freqDeps.dependencies as FreqDepParent).dependencies)) {
tree.dependencies.freqSystemDependencies = freqDeps.dependencies;
}
// to disconnect the object references inside the tree
// JSON parse/stringify is used
tree.dependencies = JSON.parse(JSON.stringify(tree.dependencies));
return tree;
}
105 changes: 52 additions & 53 deletions lib/nuget-parser/dotnet-framework-parser.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as fs from 'fs';
import * as path from 'path';
import * as dependency from './dependency';
import {Dependency, cloneShallow, fromFolderName} from './dependency';
import {parseNuspec} from './nuspec-parser';
import * as debugModule from 'debug';
const debug = debugModule('snyk');
Expand Down Expand Up @@ -29,7 +29,7 @@ function scanInstalled(installedPackages, packagesFolder) {
fs.readdirSync(packagesFolder)
.map((folderName) => {
try {
return dependency.fromFolderName(folderName);
return fromFolderName(folderName);
} catch (err) {
debug('Unable to parse dependency from folder');
debug(err);
Expand Down Expand Up @@ -59,15 +59,15 @@ function scanInstalled(installedPackages, packagesFolder) {
}

async function fetchNugetInformationFromPackages(flattenedPackageList, targetFramework) {
const nuspecParserChain: any = [];
const nugetPackageInformation: any[] = [];
// begin collecting information from .nuget files on installed packages
debug('Trying to analyze .nuspec files');
for (const name of Object.keys(flattenedPackageList)) {
const dep = flattenedPackageList[name];
debug('...' + name);
nuspecParserChain.push(await parseNuspec(dep, targetFramework));
nugetPackageInformation.push(await parseNuspec(dep, targetFramework));
}
return Promise.all(nuspecParserChain);
return nugetPackageInformation;
}

function processNugetInformation(nuspecResolutionChain) {
Expand All @@ -82,59 +82,58 @@ function processNugetInformation(nuspecResolutionChain) {
return nuspecResolutions;
}

function buildTree(node, requiredChildren, flattenedPackageList, nuspecResolutions) {
for (const requiredChild of requiredChildren) {
let transitiveDependency: Dependency;
if (flattenedPackageList[requiredChild.name]) {
// fetch from repo
transitiveDependency = cloneShallow(flattenedPackageList[requiredChild.name]);
} else {
// create as new (uninstalled)
transitiveDependency = {
dependencies: {},
name: requiredChild.name,
version: requiredChild.version,
};
}
const transitiveChildren =
(nuspecResolutions[transitiveDependency.name] &&
nuspecResolutions[transitiveDependency.name].children) || [];
buildTree(
transitiveDependency,
transitiveChildren,
flattenedPackageList,
nuspecResolutions);
node.dependencies[transitiveDependency.name] = transitiveDependency;
}
}


export async function parse(tree, manifest, targetFramework, packagesFolder) {
if (!targetFramework) {
throw new Error('No valid Dotnet target framework found');
}

const flattenedPackageList = scanInstalled(manifest, packagesFolder);
return fetchNugetInformationFromPackages(flattenedPackageList, targetFramework)
.then(processNugetInformation)
.then(function buildDependencyTree(nuspecResolutions) {
// .nuget parsing is complete, returned as array of promise resolutions
// now the flat list should be rebuilt as a tree
debug('Building dependency tree');

function buildTree(node, requiredChildren, repository) {
requiredChildren.forEach((requiredChild) => {
let transitiveDependency: dependency.Dependency;
if (flattenedPackageList[requiredChild.name]) {
// fetch from repo
transitiveDependency =
dependency.cloneShallow(flattenedPackageList[requiredChild.name]);
} else {
// create as new (uninstalled)
transitiveDependency = {
dependencies: {},
name: requiredChild.name,
version: requiredChild.version,
};
}
const transitiveChildren =
(nuspecResolutions[transitiveDependency.name] &&
nuspecResolutions[transitiveDependency.name].children) || [];
buildTree(
transitiveDependency,
transitiveChildren,
repository);
node.dependencies[transitiveDependency.name] = transitiveDependency;
});
}
const nugetPackageInformation = await fetchNugetInformationFromPackages(flattenedPackageList, targetFramework);
const nuspecResolutions = processNugetInformation(nugetPackageInformation);
// .nuget parsing is complete, returned as array of promise resolutions
// now the flat list should be rebuilt as a tree
debug('Building dependency tree');

const nugtKeys = Object.keys(nuspecResolutions);
Object.keys(flattenedPackageList).forEach((packageName) => {
tree.dependencies[packageName] =
dependency.cloneShallow(flattenedPackageList[packageName]);
});
if (nugtKeys.length > 0) {
// local folders scanned, build list from .nuspec
for (const key of nugtKeys) {
const resolution = nuspecResolutions[key];
const node = dependency.cloneShallow(flattenedPackageList[resolution.name]);
buildTree(node, resolution.children, flattenedPackageList);
tree.dependencies[node.name] = node;
}
}
return tree;
});
const nugetKeys = Object.keys(nuspecResolutions);
Object.keys(flattenedPackageList).forEach((packageName) => {
tree.dependencies[packageName] =
cloneShallow(flattenedPackageList[packageName]);
});
if (nugetKeys.length > 0) {
// local folders scanned, build list from .nuspec
for (const key of nugetKeys) {
const resolution = nuspecResolutions[key];
const node = cloneShallow(flattenedPackageList[resolution.name]);
buildTree(node, resolution.children, flattenedPackageList, nuspecResolutions);
tree.dependencies[node.name] = node;
}
}
return tree;
}
1 change: 0 additions & 1 deletion lib/nuget-parser/nuspec-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ export async function parseNuspec(dep, targetFramework) {
// We are only going to check the first targetFramework we encounter
// in the future we may want to support multiple, but only once
// we have dependency version conflict resolution implemented
// _(targetFrameworks).forEach((targetFramework) => {
_(result.package.metadata).forEach((metadata) => {
_(metadata.dependencies).forEach((rawDependency) => {

Expand Down
6 changes: 3 additions & 3 deletions lib/nuget-parser/packages-config-parser.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as parseXML from 'xml2js';
import * as debugModule from 'debug';
const debug = debugModule('snyk');
import * as dependency from './dependency';
import {Dependency, fromPackagesConfigEntry} from './dependency';

export function parse(fileContent) {
const installedPackages: dependency.Dependency[] = [];
const installedPackages: Dependency[] = [];
debug('Trying to parse packages.config manifest');
parseXML.parseString(fileContent, (err, result) => {
if (err) {
Expand All @@ -15,7 +15,7 @@ export function parse(fileContent) {
packages.forEach(
function scanPackagesConfigNode(node) {
const installedDependency =
dependency.fromPackgesConfigEntry(node);
fromPackagesConfigEntry(node);
installedPackages.push(installedDependency);
});
}
Expand Down
Loading

0 comments on commit fa6acd9

Please sign in to comment.