Skip to content

Commit 51ffe9b

Browse files
fix: optimise nuget v3 dependencies lookup (#263)
1 parent 558ff18 commit 51ffe9b

File tree

2 files changed

+33
-51
lines changed

2 files changed

+33
-51
lines changed

lib/nuget-parser/parsers/dotnet-core-v3-parser.ts

Lines changed: 25 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as debugModule from 'debug';
22
import * as depGraphLib from '@snyk/dep-graph';
33
import { DepGraphBuilder } from '@snyk/dep-graph';
44
import { InvalidManifestError } from '../../errors';
5-
import { Overrides, ProjectAssets, Target } from '../types';
5+
import { Overrides, ProjectAssets, ResolvedPackagesMap } from '../types';
66

77
const debug = debugModule('snyk');
88

@@ -16,26 +16,9 @@ export const FILTERED_DEPENDENCY_PREFIX = [
1616
'runtime',
1717
];
1818

19-
/**
20-
* Finds the actual resolved version of a package in the targets section.
21-
* This is necessary because NuGet may resolve to a different version than what's
22-
* declared in transitive dependencies due to version constraints and resolution rules.
23-
*/
24-
function findActualResolvedVersion(
25-
allPackagesForFramework: Record<string, Target>,
26-
packageName: string,
27-
): string | null {
28-
for (const key of Object.keys(allPackagesForFramework)) {
29-
if (key.startsWith(`${packageName}/`)) {
30-
return key.split('/')[1];
31-
}
32-
}
33-
return null;
34-
}
35-
3619
function recursivelyPopulateNodes(
3720
depGraphBuilder: DepGraphBuilder,
38-
allPackagesForFramework: Record<string, Target>,
21+
resolvedPackages: ResolvedPackagesMap,
3922
parentID: string,
4023
dependencies: Record<string, string>,
4124
overrides: Overrides,
@@ -58,38 +41,23 @@ function recursivelyPopulateNodes(
5841
continue;
5942
}
6043

61-
let actualResolvedVersion: string | null = childResolvedVersion;
44+
// Find the actual resolved version and target for this package name
45+
// NuGet may resolve to a different version than what's declared in transitive dependencies
46+
const resolvedPackage = resolvedPackages[childName];
47+
if (!resolvedPackage) {
48+
debug(
49+
`Child package ${childName} not found in lock file packages for framework.`,
50+
);
51+
continue;
52+
}
53+
54+
const { resolvedVersion: actualResolvedVersion, target: childPkgEntry } =
55+
resolvedPackage;
6256

63-
let childPkgEntry =
64-
allPackagesForFramework[`${childName}/${childResolvedVersion}`];
65-
if (!childPkgEntry) {
66-
// Find the actual resolved version for this package name in the targets section
67-
// NuGet may resolve to a different version than what's declared in transitive dependencies
68-
actualResolvedVersion = findActualResolvedVersion(
69-
allPackagesForFramework,
70-
childName,
57+
if (childResolvedVersion !== actualResolvedVersion) {
58+
debug(
59+
`Version mismatch for ${childName}: declared ${childResolvedVersion}, using resolved ${actualResolvedVersion}`,
7160
);
72-
if (!actualResolvedVersion) {
73-
debug(
74-
`Child package ${childName} not found in lock file packages for framework.`,
75-
);
76-
continue;
77-
}
78-
79-
if (childResolvedVersion !== actualResolvedVersion) {
80-
debug(
81-
`Version mismatch for ${childName}: declared ${childResolvedVersion}, using resolved ${actualResolvedVersion}`,
82-
);
83-
}
84-
85-
childPkgEntry =
86-
allPackagesForFramework[`${childName}/${actualResolvedVersion}`];
87-
if (!childPkgEntry) {
88-
debug(
89-
`Child package ${childName}@${actualResolvedVersion} not found in lock file packages for framework (this should not happen).`,
90-
);
91-
continue;
92-
}
9361
}
9462

9563
const childID = `${childName}@${actualResolvedVersion}`;
@@ -131,7 +99,7 @@ function recursivelyPopulateNodes(
13199

132100
recursivelyPopulateNodes(
133101
depGraphBuilder,
134-
allPackagesForFramework,
102+
resolvedPackages,
135103
childID,
136104
childPkgEntry.dependencies,
137105
overrides,
@@ -190,6 +158,12 @@ function buildDepGraph(
190158

191159
const allPackagesForFramework = projectAssets.targets[assetsTargetFramework];
192160

161+
const resolvedPackages: ResolvedPackagesMap = {};
162+
for (const [key, target] of Object.entries(allPackagesForFramework)) {
163+
const [name, version] = key.split('/');
164+
resolvedPackages[name] = { resolvedVersion: version, target };
165+
}
166+
193167
// Identify direct dependencies for the selected framework
194168
const directDependencies: Record<string, string> = {};
195169
projectAssets.projectFileDependencyGroups[assetsTargetFramework].forEach(
@@ -214,7 +188,7 @@ function buildDepGraph(
214188
// Start recursive population from direct dependencies
215189
recursivelyPopulateNodes(
216190
depGraphBuilder,
217-
allPackagesForFramework,
191+
resolvedPackages,
218192
'root-node',
219193
directDependencies, // Pass the direct dependencies object
220194
overrides,

lib/nuget-parser/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,12 @@ export type Overrides = {
114114
overrideVersion: string;
115115
};
116116

117+
export type ResolvedPackagesMap = Record<
118+
string,
119+
{
120+
readonly resolvedVersion: string;
121+
readonly target: Target;
122+
}
123+
>;
124+
117125
export type DotnetCoreV2Results = DotnetCoreV2Result[];

0 commit comments

Comments
 (0)