@@ -5,6 +5,7 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet;
5
5
using System . IO ;
6
6
using System . Linq ;
7
7
using System . Reactive . Linq ;
8
+ using System . Text . Json ;
8
9
using System . Text . RegularExpressions ;
9
10
using System . Threading . Tasks ;
10
11
using System . Xml ;
@@ -20,6 +21,7 @@ public class NuGetComponentDetector : FileComponentDetector
20
21
private static readonly IEnumerable < string > LowConfidencePackages = new [ ] { "Newtonsoft.Json" } ;
21
22
22
23
public const string NugetConfigFileName = "nuget.config" ;
24
+ public const string NugetLockfileName = "packages.lock.json" ;
23
25
24
26
private readonly IList < string > repositoryPathKeyNames = new List < string > { "repositorypath" , "globalpackagesfolder" } ;
25
27
@@ -37,7 +39,15 @@ public NuGetComponentDetector(
37
39
38
40
public override IEnumerable < string > Categories => new [ ] { Enum . GetName ( typeof ( DetectorClass ) , DetectorClass . NuGet ) } ;
39
41
40
- public override IList < string > SearchPatterns { get ; } = new List < string > { "*.nupkg" , "*.nuspec" , NugetConfigFileName , "paket.lock" } ;
42
+ public override IList < string > SearchPatterns { get ; }
43
+ = new List < string >
44
+ {
45
+ "*.nupkg" ,
46
+ "*.nuspec" ,
47
+ NugetConfigFileName ,
48
+ NugetLockfileName ,
49
+ "paket.lock" ,
50
+ } ;
41
51
42
52
public override IEnumerable < ComponentType > SupportedComponentTypes { get ; } = new [ ] { ComponentType . NuGet } ;
43
53
@@ -105,6 +115,12 @@ private async Task ProcessFileAsync(ProcessRequest processRequest)
105
115
else if ( "paket.lock" . Equals ( stream . Pattern , StringComparison . OrdinalIgnoreCase ) )
106
116
{
107
117
this . ParsePaketLock ( processRequest ) ;
118
+ return ;
119
+ }
120
+ else if ( NugetLockfileName . Equals ( stream . Pattern , StringComparison . OrdinalIgnoreCase ) )
121
+ {
122
+ await this . ParseNugetLockfileAsync ( processRequest ) ;
123
+ return ;
108
124
}
109
125
else
110
126
{
@@ -174,6 +190,29 @@ private void ParsePaketLock(ProcessRequest processRequest)
174
190
}
175
191
}
176
192
193
+ private async Task ParseNugetLockfileAsync ( ProcessRequest processRequest )
194
+ {
195
+ var singleFileComponentRecorder = processRequest . SingleFileComponentRecorder ;
196
+ var stream = processRequest . ComponentStream ;
197
+
198
+ var lockfile = await JsonSerializer . DeserializeAsync < NugetLockfileShape > ( stream . Stream ) ;
199
+ if ( lockfile . Version != 1 )
200
+ {
201
+ // only version 1 is supported
202
+ singleFileComponentRecorder . RegisterPackageParseFailure ( stream . Location ) ;
203
+ return ;
204
+ }
205
+
206
+ foreach ( var framework in lockfile . Dependencies . Values )
207
+ {
208
+ foreach ( var ( name , value ) in framework )
209
+ {
210
+ var component = new NuGetComponent ( name , value . Resolved ) ;
211
+ singleFileComponentRecorder . RegisterUsage ( new DetectedComponent ( component ) ) ;
212
+ }
213
+ }
214
+ }
215
+
177
216
private IList < DirectoryInfo > GetRepositoryPathsFromNugetConfig ( IComponentStream componentStream )
178
217
{
179
218
var potentialPaths = new List < string > ( ) ;
0 commit comments