1
1
using NuGet . Packaging ;
2
2
using NuGet . Protocol . Core . Types ;
3
+ using NuGet . Versioning ;
4
+ using NuGetUtility . PackageInformationReader ;
3
5
using NuGetUtility . Wrapper . HttpClientWrapper ;
6
+ using System . Collections . Concurrent ;
4
7
5
8
namespace NuGetUtility . LicenseValidator
6
9
{
7
10
public class LicenseValidator
8
11
{
9
12
private readonly IEnumerable < string > _allowedLicenses ;
10
- private readonly List < LicenseValidationError > _errors = new List < LicenseValidationError > ( ) ;
11
13
private readonly IFileDownloader _fileDownloader ;
12
14
private readonly Dictionary < Uri , string > _licenseMapping ;
13
- private readonly HashSet < ValidatedLicense > _validatedLicenses = new HashSet < ValidatedLicense > ( ) ;
14
15
15
16
public LicenseValidator ( Dictionary < Uri , string > licenseMapping ,
16
17
IEnumerable < string > allowedLicenses ,
@@ -21,70 +22,124 @@ public LicenseValidator(Dictionary<Uri, string> licenseMapping,
21
22
_fileDownloader = fileDownloader ;
22
23
}
23
24
24
- public async Task Validate ( IAsyncEnumerable < IPackageSearchMetadata > downloadedInfo , string context )
25
+ public async Task < IEnumerable < LicenseValidationResult > > Validate (
26
+ IAsyncEnumerable < ReferencedPackageWithContext > packages )
25
27
{
26
- await foreach ( var info in downloadedInfo )
28
+ var result = new ConcurrentDictionary < LicenseNameAndVersion , LicenseValidationResult > ( ) ;
29
+ await foreach ( var info in packages )
27
30
{
28
- if ( info . LicenseMetadata != null )
31
+ if ( info . PackageInfo . LicenseMetadata != null )
29
32
{
30
- ValidateLicenseByMetadata ( info , context ) ;
33
+ ValidateLicenseByMetadata ( info . PackageInfo , info . Context , result ) ;
31
34
}
32
- else if ( info . LicenseUrl != null )
35
+ else if ( info . PackageInfo . LicenseUrl != null )
33
36
{
34
- await ValidateLicenseByUrl ( info , context ) ;
37
+ await ValidateLicenseByUrl ( info . PackageInfo , info . Context , result ) ;
35
38
}
36
39
else
37
40
{
38
- _errors . Add ( new LicenseValidationError ( context ,
39
- info . Identity . Id ,
40
- info . Identity . Version ,
41
- "No license information found" ) ) ;
41
+ AddOrUpdateLicense ( result ,
42
+ info . PackageInfo ,
43
+ LicenseInformationOrigin . Unknown ,
44
+ new ValidationError ( "No license information found" , info . Context ) ) ;
42
45
}
43
46
}
47
+ return result . Values ;
44
48
}
45
49
46
- public IEnumerable < LicenseValidationError > GetErrors ( )
50
+ private void AddOrUpdateLicense (
51
+ ConcurrentDictionary < LicenseNameAndVersion , LicenseValidationResult > result ,
52
+ IPackageSearchMetadata info ,
53
+ LicenseInformationOrigin origin ,
54
+ ValidationError error ,
55
+ string ? license = null )
47
56
{
48
- return _errors ;
57
+ var newValue = new LicenseValidationResult (
58
+ info . Identity . Id ,
59
+ info . Identity . Version ,
60
+ info . ProjectUrl ? . ToString ( ) ,
61
+ license ,
62
+ origin ,
63
+ new List < ValidationError > { error } ) ;
64
+ result . AddOrUpdate ( new LicenseNameAndVersion ( info . Identity . Id , info . Identity . Version ) ,
65
+ key => CreateResult ( key , newValue ) ,
66
+ ( key , oldValue ) => UpdateResult ( key , oldValue , newValue ) ) ;
49
67
}
50
68
51
- public IEnumerable < ValidatedLicense > GetValidatedLicenses ( )
69
+ private void AddOrUpdateLicense (
70
+ ConcurrentDictionary < LicenseNameAndVersion , LicenseValidationResult > result ,
71
+ IPackageSearchMetadata info ,
72
+ LicenseInformationOrigin origin ,
73
+ string ? license = null )
52
74
{
53
- return _validatedLicenses ;
75
+ var newValue = new LicenseValidationResult (
76
+ info . Identity . Id ,
77
+ info . Identity . Version ,
78
+ info . ProjectUrl ? . ToString ( ) ,
79
+ license ,
80
+ origin ) ;
81
+ result . AddOrUpdate ( new LicenseNameAndVersion ( info . Identity . Id , info . Identity . Version ) ,
82
+ key => CreateResult ( key , newValue ) ,
83
+ ( key , oldValue ) => UpdateResult ( key , oldValue , newValue ) ) ;
54
84
}
55
85
56
- private void ValidateLicenseByMetadata ( IPackageSearchMetadata info , string context )
86
+ private LicenseValidationResult UpdateResult ( LicenseNameAndVersion _ ,
87
+ LicenseValidationResult oldValue ,
88
+ LicenseValidationResult newValue )
89
+ {
90
+ oldValue . ValidationErrors . AddRange ( newValue . ValidationErrors ) ;
91
+ if ( oldValue . License is null && newValue . License is not null )
92
+ {
93
+ oldValue . License = newValue . License ;
94
+ oldValue . LicenseInformationOrigin = newValue . LicenseInformationOrigin ;
95
+ }
96
+ return oldValue ;
97
+ }
98
+
99
+ private LicenseValidationResult CreateResult ( LicenseNameAndVersion _ , LicenseValidationResult newValue )
100
+ {
101
+ return newValue ;
102
+ }
103
+
104
+ private void ValidateLicenseByMetadata ( IPackageSearchMetadata info ,
105
+ string context ,
106
+ ConcurrentDictionary < LicenseNameAndVersion , LicenseValidationResult > result )
57
107
{
58
108
switch ( info . LicenseMetadata ! . Type )
59
109
{
60
110
case LicenseType . Expression :
61
111
var licenseId = info . LicenseMetadata ! . License ;
62
112
if ( IsLicenseValid ( licenseId ) )
63
113
{
64
- _validatedLicenses . Add ( new ValidatedLicense ( info . Identity . Id ,
65
- info . Identity . Version ,
66
- info . LicenseMetadata . License ,
67
- LicenseInformationOrigin . Expression ) ) ;
114
+ AddOrUpdateLicense ( result ,
115
+ info ,
116
+ LicenseInformationOrigin . Expression ,
117
+ info . LicenseMetadata . License ) ;
68
118
}
69
119
else
70
120
{
71
- _errors . Add ( new LicenseValidationError ( context ,
72
- info . Identity . Id ,
73
- info . Identity . Version ,
74
- GetLicenseNotAllowedMessage ( info . LicenseMetadata . License ) ) ) ;
121
+ AddOrUpdateLicense ( result ,
122
+ info ,
123
+ LicenseInformationOrigin . Expression ,
124
+ new ValidationError ( GetLicenseNotAllowedMessage ( info . LicenseMetadata . License ) , context ) ,
125
+ info . LicenseMetadata . License ) ;
75
126
}
76
127
77
128
break ;
78
129
default :
79
- _errors . Add ( new LicenseValidationError ( context ,
80
- info . Identity . Id ,
81
- info . Identity . Version ,
82
- $ "Validation for licenses of type { info . LicenseMetadata ! . Type } not yet supported") ) ;
130
+ AddOrUpdateLicense ( result ,
131
+ info ,
132
+ LicenseInformationOrigin . Unknown ,
133
+ new ValidationError (
134
+ $ "Validation for licenses of type { info . LicenseMetadata ! . Type } not yet supported",
135
+ context ) ) ;
83
136
break ;
84
137
}
85
138
}
86
139
87
- private async Task ValidateLicenseByUrl ( IPackageSearchMetadata info , string context )
140
+ private async Task ValidateLicenseByUrl ( IPackageSearchMetadata info ,
141
+ string context ,
142
+ ConcurrentDictionary < LicenseNameAndVersion , LicenseValidationResult > result )
88
143
{
89
144
if ( info . LicenseUrl . IsAbsoluteUri )
90
145
{
@@ -103,32 +158,34 @@ await _fileDownloader.DownloadFile(info.LicenseUrl,
103
158
{
104
159
if ( IsLicenseValid ( licenseId ) )
105
160
{
106
- _validatedLicenses . Add ( new ValidatedLicense ( info . Identity . Id ,
107
- info . Identity . Version ,
108
- licenseId ,
109
- LicenseInformationOrigin . Url ) ) ;
161
+ AddOrUpdateLicense ( result ,
162
+ info ,
163
+ LicenseInformationOrigin . Url ,
164
+ licenseId ) ;
110
165
}
111
166
else
112
167
{
113
- _errors . Add ( new LicenseValidationError ( context ,
114
- info . Identity . Id ,
115
- info . Identity . Version ,
116
- GetLicenseNotAllowedMessage ( licenseId ) ) ) ;
168
+ AddOrUpdateLicense ( result ,
169
+ info ,
170
+ LicenseInformationOrigin . Url ,
171
+ new ValidationError ( GetLicenseNotAllowedMessage ( licenseId ) , context ) ,
172
+ licenseId ) ;
117
173
}
118
174
}
119
175
else if ( ! _allowedLicenses . Any ( ) )
120
176
{
121
- _validatedLicenses . Add ( new ValidatedLicense ( info . Identity . Id ,
122
- info . Identity . Version ,
123
- info . LicenseUrl . ToString ( ) ,
124
- LicenseInformationOrigin . Url ) ) ;
177
+ AddOrUpdateLicense ( result ,
178
+ info ,
179
+ LicenseInformationOrigin . Url ,
180
+ info . LicenseUrl . ToString ( ) ) ;
125
181
}
126
182
else
127
183
{
128
- _errors . Add ( new LicenseValidationError ( context ,
129
- info . Identity . Id ,
130
- info . Identity . Version ,
131
- $ "Cannot determine License type for url { info . LicenseUrl } ") ) ;
184
+ AddOrUpdateLicense ( result ,
185
+ info ,
186
+ LicenseInformationOrigin . Url ,
187
+ new ValidationError ( $ "Cannot determine License type for url { info . LicenseUrl } ", context ) ,
188
+ info . LicenseUrl . ToString ( ) ) ;
132
189
}
133
190
}
134
191
@@ -154,5 +211,7 @@ private string GetLicenseNotAllowedMessage(string license)
154
211
{
155
212
return $ "License { license } not found in list of supported licenses";
156
213
}
214
+
215
+ private record LicenseNameAndVersion ( string LicenseName , NuGetVersion Version ) ;
157
216
}
158
217
}
0 commit comments