dependabot-nuget 0.297.2 → 0.299.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +15 -14
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/SupportedFrameworks.cs +16 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +131 -45
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/EOLHandling.cs +78 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +50 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +26 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/FrameworkChecker/CompatibilityCheckerFacts.cs +2 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/MiscellaneousTests.cs +29 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +485 -77
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatedDependencyListTests.cs +48 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/EOLHandlingTests.cs +23 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +8 -0
- data/lib/dependabot/nuget/file_fetcher.rb +1 -0
- data/lib/dependabot/nuget/native_helpers.rb +16 -0
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47471c96a0fec7881b5454528d6cd07199cd600b1ec4dde66656fc754db318fe
|
4
|
+
data.tar.gz: 2364b4e071736115c1cb9503dc40562819e4c376198321761812c70dc309f1bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d31e631d9c1dd411843c4c911ad2db4e8a19f4d1fd15ffb0e5c2d4af1b092520bcc4aea2b31996c765870973e0da47b85910fb7d14f81ca973a7069554dc6733
|
7
|
+
data.tar.gz: 48714dea50d6fab935c7ca952e5d992f9aaf0699a54f99f576db55575b36251af0b7503744d229d187245b7e1eab687ce639fad574c8b15bb795f569720a0c99
|
@@ -62,23 +62,24 @@ internal static class VersionFinder
|
|
62
62
|
|
63
63
|
foreach (var source in sources)
|
64
64
|
{
|
65
|
-
|
66
|
-
|
67
|
-
if (feed is null)
|
65
|
+
MetadataResource? feed = null;
|
66
|
+
try
|
68
67
|
{
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
var sourceRepository = Repository.Factory.GetCoreV3(source);
|
69
|
+
feed = await sourceRepository.GetResourceAsync<MetadataResource>();
|
70
|
+
if (feed is null)
|
71
|
+
{
|
72
|
+
logger.Warn($"Failed to get {nameof(MetadataResource)} for [{source.Source}]");
|
73
|
+
continue;
|
74
|
+
}
|
72
75
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
76
|
+
var packageFinder = await sourceRepository.GetResourceAsync<FindPackageByIdResource>();
|
77
|
+
if (packageFinder is null)
|
78
|
+
{
|
79
|
+
logger.Warn($"Failed to get {nameof(FindPackageByIdResource)} for [{source.Source}]");
|
80
|
+
continue;
|
81
|
+
}
|
79
82
|
|
80
|
-
try
|
81
|
-
{
|
82
83
|
// a non-compliant v2 API returning 404 can cause this to throw
|
83
84
|
var existsInFeed = await feed.Exists(
|
84
85
|
packageId,
|
@@ -20,7 +20,8 @@ namespace NuGetGallery.Frameworks
|
|
20
20
|
/// </remarks>
|
21
21
|
public static class SupportedFrameworks
|
22
22
|
{
|
23
|
-
public static readonly Version Version8 = new Version(8, 0, 0, 0);
|
23
|
+
public static readonly Version Version8 = new Version(8, 0, 0, 0);
|
24
|
+
public static readonly Version Version9 = new Version(9, 0, 0, 0);
|
24
25
|
|
25
26
|
public static readonly NuGetFramework MonoAndroid = new NuGetFramework(FrameworkIdentifiers.MonoAndroid, EmptyVersion);
|
26
27
|
public static readonly NuGetFramework MonoTouch = new NuGetFramework(FrameworkIdentifiers.MonoTouch, EmptyVersion);
|
@@ -29,12 +30,14 @@ namespace NuGetGallery.Frameworks
|
|
29
30
|
public static readonly NuGetFramework Net48 = new NuGetFramework(FrameworkIdentifiers.Net, new Version(4, 8, 0, 0));
|
30
31
|
public static readonly NuGetFramework Net481 = new NuGetFramework(FrameworkIdentifiers.Net, new Version(4, 8, 1, 0));
|
31
32
|
public static readonly NuGetFramework Net50Windows = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version5, "windows", EmptyVersion);
|
33
|
+
|
32
34
|
public static readonly NuGetFramework Net60Android = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version6, "android", EmptyVersion);
|
33
35
|
public static readonly NuGetFramework Net60Ios = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version6, "ios", EmptyVersion);
|
34
36
|
public static readonly NuGetFramework Net60MacOs = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version6, "macos", EmptyVersion);
|
35
37
|
public static readonly NuGetFramework Net60MacCatalyst = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version6, "maccatalyst", EmptyVersion);
|
36
38
|
public static readonly NuGetFramework Net60TvOs = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version6, "tvos", EmptyVersion);
|
37
39
|
public static readonly NuGetFramework Net60Windows = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version6, "windows", EmptyVersion);
|
40
|
+
|
38
41
|
public static readonly NuGetFramework Net70Android = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version7, "android", EmptyVersion);
|
39
42
|
public static readonly NuGetFramework Net70Ios = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version7, "ios", EmptyVersion);
|
40
43
|
public static readonly NuGetFramework Net70MacOs = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version7, "macos", EmptyVersion);
|
@@ -42,14 +45,22 @@ namespace NuGetGallery.Frameworks
|
|
42
45
|
public static readonly NuGetFramework Net70TvOs = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version7, "tvos", EmptyVersion);
|
43
46
|
public static readonly NuGetFramework Net70Windows = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version7, "windows", EmptyVersion);
|
44
47
|
|
45
|
-
public static readonly NuGetFramework Net80 = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version8);
|
46
|
-
|
48
|
+
public static readonly NuGetFramework Net80 = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version8);
|
47
49
|
public static readonly NuGetFramework Net80Android = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version8, "android", EmptyVersion);
|
48
50
|
public static readonly NuGetFramework Net80Ios = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version8, "ios", EmptyVersion);
|
49
51
|
public static readonly NuGetFramework Net80MacOs = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version8, "macos", EmptyVersion);
|
50
52
|
public static readonly NuGetFramework Net80MacCatalyst = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version8, "maccatalyst", EmptyVersion);
|
51
53
|
public static readonly NuGetFramework Net80TvOs = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version8, "tvos", EmptyVersion);
|
52
54
|
public static readonly NuGetFramework Net80Windows = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version8, "windows", EmptyVersion);
|
55
|
+
|
56
|
+
public static readonly NuGetFramework Net90 = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version9);
|
57
|
+
public static readonly NuGetFramework Net90Android = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version9, "android", EmptyVersion);
|
58
|
+
public static readonly NuGetFramework Net90Ios = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version9, "ios", EmptyVersion);
|
59
|
+
public static readonly NuGetFramework Net90MacOs = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version9, "macos", EmptyVersion);
|
60
|
+
public static readonly NuGetFramework Net90MacCatalyst = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version9, "maccatalyst", EmptyVersion);
|
61
|
+
public static readonly NuGetFramework Net90TvOs = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version9, "tvos", EmptyVersion);
|
62
|
+
public static readonly NuGetFramework Net90Windows = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version9, "windows", EmptyVersion);
|
63
|
+
|
53
64
|
public static readonly NuGetFramework NetCore = new NuGetFramework(FrameworkIdentifiers.NetCore, EmptyVersion);
|
54
65
|
public static readonly NuGetFramework NetMf = new NuGetFramework(FrameworkIdentifiers.NetMicro, EmptyVersion);
|
55
66
|
public static readonly NuGetFramework UAP = new NuGetFramework(FrameworkIdentifiers.UAP, EmptyVersion);
|
@@ -75,6 +86,7 @@ namespace NuGetGallery.Frameworks
|
|
75
86
|
Net60, Net60Android, Net60Ios, Net60MacCatalyst, Net60MacOs, Net60TvOs, Net60Windows,
|
76
87
|
Net70, Net70Android, Net70Ios, Net70MacCatalyst, Net70MacOs, Net70TvOs, Net70Windows,
|
77
88
|
Net80, Net80Android, Net80Ios, Net80MacCatalyst, Net80MacOs, Net80TvOs, Net80Windows,
|
89
|
+
Net90, Net90Android, Net90Ios, Net90MacCatalyst, Net90MacOs, Net90TvOs, Net90Windows,
|
78
90
|
NetCore, NetCore45, NetCore451,
|
79
91
|
NetCoreApp10, NetCoreApp11, NetCoreApp20, NetCoreApp21, NetCoreApp22, NetCoreApp30, NetCoreApp31,
|
80
92
|
NetMf,
|
@@ -94,6 +106,7 @@ namespace NuGetGallery.Frameworks
|
|
94
106
|
{
|
95
107
|
public static readonly List<NuGetFramework> NetTfms =
|
96
108
|
[
|
109
|
+
Net90,
|
97
110
|
Net80,
|
98
111
|
Net70,
|
99
112
|
Net60,
|
@@ -3,6 +3,7 @@ using System.Net;
|
|
3
3
|
using System.Text;
|
4
4
|
using System.Text.Json;
|
5
5
|
using System.Text.Json.Serialization;
|
6
|
+
using System.Text.RegularExpressions;
|
6
7
|
|
7
8
|
using Microsoft.Extensions.FileSystemGlobbing;
|
8
9
|
|
@@ -13,6 +14,8 @@ using NuGetUpdater.Core.Discover;
|
|
13
14
|
using NuGetUpdater.Core.Run.ApiModel;
|
14
15
|
using NuGetUpdater.Core.Utilities;
|
15
16
|
|
17
|
+
using static NuGetUpdater.Core.Utilities.EOLHandling;
|
18
|
+
|
16
19
|
namespace NuGetUpdater.Core.Run;
|
17
20
|
|
18
21
|
public class RunWorker
|
@@ -122,6 +125,7 @@ public class RunWorker
|
|
122
125
|
|
123
126
|
// TODO: pull out relevant dependencies, then check each for updates and track the changes
|
124
127
|
var originalDependencyFileContents = new Dictionary<string, string>();
|
128
|
+
var originalDependencyFileEOFs = new Dictionary<string, EOLType>();
|
125
129
|
var actualUpdatedDependencies = new List<ReportedDependency>();
|
126
130
|
|
127
131
|
// track original contents for later handling
|
@@ -131,6 +135,7 @@ public class RunWorker
|
|
131
135
|
var localFullPath = Path.Join(repoContentsPath.FullName, repoFullPath);
|
132
136
|
var content = await File.ReadAllTextAsync(localFullPath);
|
133
137
|
originalDependencyFileContents[repoFullPath] = content;
|
138
|
+
originalDependencyFileEOFs[repoFullPath] = content.GetPredominantEOL();
|
134
139
|
}
|
135
140
|
|
136
141
|
foreach (var project in discoveryResult.Projects)
|
@@ -142,20 +147,43 @@ public class RunWorker
|
|
142
147
|
var extraFilePath = Path.Join(projectDirectory, extraFile);
|
143
148
|
await TrackOriginalContentsAsync(discoveryResult.Path, extraFilePath);
|
144
149
|
}
|
145
|
-
|
150
|
+
}
|
151
|
+
|
152
|
+
var nonProjectFiles = new[]
|
153
|
+
{
|
154
|
+
discoveryResult.GlobalJson?.FilePath,
|
155
|
+
discoveryResult.DotNetToolsJson?.FilePath,
|
156
|
+
}.Where(f => f is not null).Cast<string>().ToArray();
|
157
|
+
foreach (var nonProjectFile in nonProjectFiles)
|
158
|
+
{
|
159
|
+
await TrackOriginalContentsAsync(discoveryResult.Path, nonProjectFile);
|
146
160
|
}
|
147
161
|
|
148
162
|
// do update
|
149
163
|
var updateOperations = GetUpdateOperations(discoveryResult).ToArray();
|
150
|
-
|
164
|
+
var allowedUpdateOperations = updateOperations.Where(u => IsUpdateAllowed(job, u.Dependency)).ToArray();
|
165
|
+
|
166
|
+
// requested update isn't listed => SecurityUpdateNotNeeded
|
167
|
+
var expectedSecurityUpdateDependencyNames = job.SecurityAdvisories
|
168
|
+
.Select(s => s.DependencyName)
|
169
|
+
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
170
|
+
var actualUpdateDependencyNames = allowedUpdateOperations
|
171
|
+
.Select(u => u.Dependency.Name)
|
172
|
+
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
173
|
+
var expectedDependencyUpdateMissingInActual = expectedSecurityUpdateDependencyNames
|
174
|
+
.Except(actualUpdateDependencyNames, StringComparer.OrdinalIgnoreCase)
|
175
|
+
.OrderBy(d => d, StringComparer.OrdinalIgnoreCase)
|
176
|
+
.ToArray();
|
177
|
+
|
178
|
+
foreach (var missingSecurityUpdate in expectedDependencyUpdateMissingInActual)
|
151
179
|
{
|
152
|
-
|
153
|
-
|
154
|
-
{
|
155
|
-
continue;
|
156
|
-
}
|
180
|
+
await _apiHandler.RecordUpdateJobError(new SecurityUpdateNotNeeded(missingSecurityUpdate));
|
181
|
+
}
|
157
182
|
|
158
|
-
|
183
|
+
foreach (var updateOperation in allowedUpdateOperations)
|
184
|
+
{
|
185
|
+
var dependency = updateOperation.Dependency;
|
186
|
+
_logger.Info($"Updating [{dependency.Name}] in [{updateOperation.FilePath}]");
|
159
187
|
|
160
188
|
var dependencyInfo = GetDependencyInfo(job, dependency);
|
161
189
|
var analysisResult = await _analyzeWorker.RunAsync(repoContentsPath.FullName, discoveryResult, dependencyInfo);
|
@@ -164,7 +192,7 @@ public class RunWorker
|
|
164
192
|
{
|
165
193
|
// TODO: this is inefficient, but not likely causing a bottleneck
|
166
194
|
var previousDependency = discoveredUpdatedDependencies.Dependencies
|
167
|
-
.Single(d => d.Name == dependency.Name && d.Requirements.Single().File == updateOperation.
|
195
|
+
.Single(d => d.Name == dependency.Name && d.Requirements.Single().File == updateOperation.FilePath);
|
168
196
|
var updatedDependency = new ReportedDependency()
|
169
197
|
{
|
170
198
|
Name = dependency.Name,
|
@@ -173,7 +201,7 @@ public class RunWorker
|
|
173
201
|
[
|
174
202
|
new ReportedRequirement()
|
175
203
|
{
|
176
|
-
File = updateOperation.
|
204
|
+
File = updateOperation.FilePath,
|
177
205
|
Requirement = analysisResult.UpdatedVersion,
|
178
206
|
Groups = previousDependency.Requirements.Single().Groups,
|
179
207
|
Source = new RequirementSource()
|
@@ -186,7 +214,7 @@ public class RunWorker
|
|
186
214
|
PreviousRequirements = previousDependency.Requirements,
|
187
215
|
};
|
188
216
|
|
189
|
-
var updateResult = await _updaterWorker.RunAsync(repoContentsPath.FullName, updateOperation.
|
217
|
+
var updateResult = await _updaterWorker.RunAsync(repoContentsPath.FullName, updateOperation.FilePath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, isTransitive: dependency.IsTransitive);
|
190
218
|
// TODO: need to report if anything was actually updated
|
191
219
|
if (updateResult.Error is null)
|
192
220
|
{
|
@@ -203,6 +231,10 @@ public class RunWorker
|
|
203
231
|
var localFullPath = Path.GetFullPath(Path.Join(repoContentsPath.FullName, repoFullPath));
|
204
232
|
var originalContent = originalDependencyFileContents[repoFullPath];
|
205
233
|
var updatedContent = await File.ReadAllTextAsync(localFullPath);
|
234
|
+
|
235
|
+
updatedContent = updatedContent.SetEOL(originalDependencyFileEOFs[repoFullPath]);
|
236
|
+
await File.WriteAllTextAsync(localFullPath, updatedContent);
|
237
|
+
|
206
238
|
if (updatedContent != originalContent)
|
207
239
|
{
|
208
240
|
updatedDependencyFiles[localFullPath] = new DependencyFile()
|
@@ -223,7 +255,11 @@ public class RunWorker
|
|
223
255
|
var extraFilePath = Path.Join(projectDirectory, extraFile);
|
224
256
|
await AddUpdatedFileIfDifferentAsync(discoveryResult.Path, extraFilePath);
|
225
257
|
}
|
226
|
-
|
258
|
+
}
|
259
|
+
|
260
|
+
foreach (var nonProjectFile in nonProjectFiles)
|
261
|
+
{
|
262
|
+
await AddUpdatedFileIfDifferentAsync(discoveryResult.Path, nonProjectFile);
|
227
263
|
}
|
228
264
|
|
229
265
|
if (updatedDependencyFiles.Count > 0)
|
@@ -266,34 +302,50 @@ public class RunWorker
|
|
266
302
|
return result;
|
267
303
|
}
|
268
304
|
|
269
|
-
internal static IEnumerable<(string
|
305
|
+
internal static IEnumerable<(string FilePath, Dependency Dependency)> GetUpdateOperations(WorkspaceDiscoveryResult discovery)
|
270
306
|
{
|
271
|
-
// discovery is grouped by project then dependency, but we want to pivot and return a list of update operations sorted by dependency name then
|
307
|
+
// discovery is grouped by project/file then dependency, but we want to pivot and return a list of update operations sorted by dependency name then file path
|
272
308
|
|
273
309
|
var updateOrder = new Dictionary<string, Dictionary<string, Dictionary<string, Dependency>>>(StringComparer.OrdinalIgnoreCase);
|
274
|
-
// <dependency name,
|
310
|
+
// <dependency name, <file path, specific dependencies>>
|
275
311
|
|
276
312
|
// collect
|
277
|
-
|
313
|
+
void CollectDependenciesForFile(string filePath, IEnumerable<Dependency> dependencies)
|
278
314
|
{
|
279
|
-
var
|
280
|
-
foreach (var dependency in project.Dependencies)
|
315
|
+
foreach (var dependency in dependencies)
|
281
316
|
{
|
282
317
|
var dependencyGroup = updateOrder.GetOrAdd(dependency.Name, () => new Dictionary<string, Dictionary<string, Dependency>>(PathComparer.Instance));
|
283
|
-
var
|
284
|
-
|
318
|
+
var dependenciesForFile = dependencyGroup.GetOrAdd(filePath, () => new Dictionary<string, Dependency>(StringComparer.OrdinalIgnoreCase));
|
319
|
+
dependenciesForFile[dependency.Name] = dependency;
|
285
320
|
}
|
286
321
|
}
|
322
|
+
foreach (var project in discovery.Projects)
|
323
|
+
{
|
324
|
+
var projectPath = Path.Join(discovery.Path, project.FilePath).FullyNormalizedRootedPath();
|
325
|
+
CollectDependenciesForFile(projectPath, project.Dependencies);
|
326
|
+
}
|
327
|
+
|
328
|
+
if (discovery.GlobalJson is not null)
|
329
|
+
{
|
330
|
+
var globalJsonPath = Path.Join(discovery.Path, discovery.GlobalJson.FilePath).FullyNormalizedRootedPath();
|
331
|
+
CollectDependenciesForFile(globalJsonPath, discovery.GlobalJson.Dependencies);
|
332
|
+
}
|
333
|
+
|
334
|
+
if (discovery.DotNetToolsJson is not null)
|
335
|
+
{
|
336
|
+
var dotnetToolsJsonPath = Path.Join(discovery.Path, discovery.DotNetToolsJson.FilePath).FullyNormalizedRootedPath();
|
337
|
+
CollectDependenciesForFile(dotnetToolsJsonPath, discovery.DotNetToolsJson.Dependencies);
|
338
|
+
}
|
287
339
|
|
288
340
|
// return
|
289
341
|
foreach (var dependencyName in updateOrder.Keys.OrderBy(k => k, StringComparer.OrdinalIgnoreCase))
|
290
342
|
{
|
291
|
-
var
|
292
|
-
foreach (var
|
343
|
+
var fileDependencies = updateOrder[dependencyName];
|
344
|
+
foreach (var filePath in fileDependencies.Keys.OrderBy(p => p, PathComparer.Instance))
|
293
345
|
{
|
294
|
-
var dependencies =
|
346
|
+
var dependencies = fileDependencies[filePath];
|
295
347
|
var dependency = dependencies[dependencyName];
|
296
|
-
yield return (
|
348
|
+
yield return (filePath, dependency);
|
297
349
|
}
|
298
350
|
}
|
299
351
|
}
|
@@ -440,35 +492,69 @@ public class RunWorker
|
|
440
492
|
}
|
441
493
|
}
|
442
494
|
|
495
|
+
var allDependenciesWithFilePath = discoveryResult.Projects.SelectMany(p =>
|
496
|
+
{
|
497
|
+
return p.Dependencies
|
498
|
+
.Where(d => d.Version is not null)
|
499
|
+
.Select(d =>
|
500
|
+
(p.FilePath, new ReportedDependency()
|
501
|
+
{
|
502
|
+
Name = d.Name,
|
503
|
+
Requirements = [new ReportedRequirement()
|
504
|
+
{
|
505
|
+
File = GetFullRepoPath(p.FilePath),
|
506
|
+
Requirement = d.Version!,
|
507
|
+
Groups = ["dependencies"],
|
508
|
+
}],
|
509
|
+
Version = d.Version,
|
510
|
+
}));
|
511
|
+
}).ToList();
|
512
|
+
|
513
|
+
var nonProjectDependencySet = new (string?, IEnumerable<Dependency>)[]
|
514
|
+
{
|
515
|
+
(discoveryResult.GlobalJson?.FilePath, discoveryResult.GlobalJson?.Dependencies ?? []),
|
516
|
+
(discoveryResult.DotNetToolsJson?.FilePath, discoveryResult.DotNetToolsJson?.Dependencies ?? []),
|
517
|
+
};
|
518
|
+
|
519
|
+
foreach (var (filePath, dependencies) in nonProjectDependencySet)
|
520
|
+
{
|
521
|
+
if (filePath is null)
|
522
|
+
{
|
523
|
+
continue;
|
524
|
+
}
|
525
|
+
|
526
|
+
allDependenciesWithFilePath.AddRange(dependencies
|
527
|
+
.Where(d => d.Version is not null)
|
528
|
+
.Select(d =>
|
529
|
+
(filePath, new ReportedDependency()
|
530
|
+
{
|
531
|
+
Name = d.Name,
|
532
|
+
Requirements = [new ReportedRequirement()
|
533
|
+
{
|
534
|
+
File = GetFullRepoPath(filePath),
|
535
|
+
Requirement = d.Version!,
|
536
|
+
Groups = ["dependencies"],
|
537
|
+
}],
|
538
|
+
Version = d.Version,
|
539
|
+
})));
|
540
|
+
}
|
541
|
+
|
542
|
+
var sortedDependencies = allDependenciesWithFilePath
|
543
|
+
.OrderBy(pair => Path.Join(discoveryResult.Path, pair.FilePath).FullyNormalizedRootedPath(), PathComparer.Instance)
|
544
|
+
.ThenBy(pair => pair.Item2.Name, StringComparer.OrdinalIgnoreCase)
|
545
|
+
.Select(pair => pair.Item2)
|
546
|
+
.ToArray();
|
547
|
+
|
443
548
|
var dependencyFiles = discoveryResult.Projects
|
444
549
|
.Select(p => GetFullRepoPath(p.FilePath))
|
445
550
|
.Concat(auxiliaryFiles)
|
446
551
|
.Distinct()
|
447
552
|
.OrderBy(p => p)
|
448
553
|
.ToArray();
|
449
|
-
|
450
|
-
.OrderBy(p => Path.Join(discoveryResult.Path, p.FilePath).FullyNormalizedRootedPath(), PathComparer.Instance)
|
451
|
-
.ToArray();
|
554
|
+
|
452
555
|
var updatedDependencyList = new UpdatedDependencyList()
|
453
556
|
{
|
454
|
-
Dependencies =
|
455
|
-
{
|
456
|
-
return p.Dependencies
|
457
|
-
.Where(d => d.Version is not null)
|
458
|
-
.OrderBy(d => d.Name, StringComparer.OrdinalIgnoreCase)
|
459
|
-
.Select(d =>
|
460
|
-
new ReportedDependency()
|
461
|
-
{
|
462
|
-
Name = d.Name,
|
463
|
-
Requirements = [new ReportedRequirement()
|
464
|
-
{
|
465
|
-
File = GetFullRepoPath(p.FilePath),
|
466
|
-
Requirement = d.Version!,
|
467
|
-
Groups = ["dependencies"],
|
468
|
-
}],
|
469
|
-
Version = d.Version,
|
470
|
-
});
|
471
|
-
}).ToArray(),
|
557
|
+
Dependencies = sortedDependencies,
|
472
558
|
DependencyFiles = dependencyFiles,
|
473
559
|
};
|
474
560
|
return updatedDependencyList;
|
@@ -0,0 +1,78 @@
|
|
1
|
+
using System.Text.RegularExpressions;
|
2
|
+
|
3
|
+
namespace NuGetUpdater.Core.Utilities;
|
4
|
+
|
5
|
+
public static class EOLHandling
|
6
|
+
{
|
7
|
+
/// <summary>
|
8
|
+
/// Used to save (and then restore) which line endings are predominant in a file.
|
9
|
+
/// </summary>
|
10
|
+
public enum EOLType
|
11
|
+
{
|
12
|
+
/// <summary>
|
13
|
+
/// Line feed - \n
|
14
|
+
/// Typical on most systems.
|
15
|
+
/// </summary>
|
16
|
+
LF,
|
17
|
+
/// <summary>
|
18
|
+
/// Carriage return - \r
|
19
|
+
/// Typical on older MacOS, unlikely (but possible) to come up here
|
20
|
+
/// </summary>
|
21
|
+
CR,
|
22
|
+
/// <summary>
|
23
|
+
/// Carriage return and line feed - \r\n.
|
24
|
+
/// Typical on Windows
|
25
|
+
/// </summary>
|
26
|
+
CRLF
|
27
|
+
};
|
28
|
+
|
29
|
+
/// <summary>
|
30
|
+
/// Analyze the input string and find the most common line ending type.
|
31
|
+
/// </summary>
|
32
|
+
/// <param name="content">The string to analyze</param>
|
33
|
+
/// <returns>The most common type of line ending in the input string.</returns>
|
34
|
+
public static EOLType GetPredominantEOL(this string content)
|
35
|
+
{
|
36
|
+
// Get stats on EOL characters/character sequences, if one predominates choose that for writing later.
|
37
|
+
var lfcount = content.Count(c => c == '\n');
|
38
|
+
var crcount = content.Count(c => c == '\r');
|
39
|
+
var crlfcount = Regex.Matches(content, "\r\n").Count();
|
40
|
+
|
41
|
+
// Since CRLF contains both a CR and a LF, subtract it from those counts
|
42
|
+
lfcount -= crlfcount;
|
43
|
+
crcount -= crlfcount;
|
44
|
+
if (crcount > lfcount && crcount > crlfcount)
|
45
|
+
{
|
46
|
+
return EOLType.CR;
|
47
|
+
}
|
48
|
+
else if (crlfcount > lfcount)
|
49
|
+
{
|
50
|
+
return EOLType.CRLF;
|
51
|
+
}
|
52
|
+
else
|
53
|
+
{
|
54
|
+
return EOLType.LF;
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
/// <summary>
|
59
|
+
/// Given a line ending, modify the input string to uniformly use that line ending.
|
60
|
+
/// </summary>
|
61
|
+
/// <param name="content">The input string, which may have any combination of line endings.</param>
|
62
|
+
/// <param name="desiredEOL">The line ending type to use across the result.</param>
|
63
|
+
/// <returns>The string with any line endings swapped to the desired type.</returns>
|
64
|
+
/// <exception cref="ArgumentOutOfRangeException">If EOLType is an unexpected value.</exception>
|
65
|
+
public static string SetEOL(this string content, EOLType desiredEOL)
|
66
|
+
{
|
67
|
+
switch (desiredEOL)
|
68
|
+
{
|
69
|
+
case EOLType.LF:
|
70
|
+
return Regex.Replace(content, "(\r\n|\r)", "\n");
|
71
|
+
case EOLType.CR:
|
72
|
+
return Regex.Replace(content, "(\r\n|\n)", "\r");
|
73
|
+
case EOLType.CRLF:
|
74
|
+
return Regex.Replace(content, "(\r\n|\r|\n)", "\r\n");
|
75
|
+
}
|
76
|
+
throw new ArgumentOutOfRangeException(nameof(desiredEOL));
|
77
|
+
}
|
78
|
+
}
|
@@ -795,7 +795,7 @@ internal static partial class MSBuildHelper
|
|
795
795
|
);
|
796
796
|
return (exitCode, stdOut, stdErr);
|
797
797
|
});
|
798
|
-
|
798
|
+
ThrowOnError(stdOut);
|
799
799
|
if (exitCode != 0)
|
800
800
|
{
|
801
801
|
logger.Warn($"Error determining target frameworks.\nSTDOUT:\n{stdOut}\nSTDERR:\n{stdErr}");
|
@@ -975,6 +975,7 @@ internal static partial class MSBuildHelper
|
|
975
975
|
new Regex(@"Package '(?<PackageName>[^']*)' is not found on source '(?<PackageSource>[^$\r\n]*)'\."),
|
976
976
|
new Regex(@"Unable to find package (?<PackageName>[^ ]+)\. No packages exist with this id in source\(s\): (?<PackageSource>.*)$", RegexOptions.Multiline),
|
977
977
|
new Regex(@"Unable to find package (?<PackageName>[^ ]+) with version \((?<PackageVersion>[^)]+)\)"),
|
978
|
+
new Regex(@"Could not resolve SDK ""(?<PackageName>[^ ]+)""\."),
|
978
979
|
};
|
979
980
|
var matches = patterns.Select(p => p.Match(output)).Where(m => m.Success);
|
980
981
|
if (matches.Any())
|
@@ -1300,6 +1300,56 @@ public partial class AnalyzeWorkerTests : AnalyzeWorkerTestBase
|
|
1300
1300
|
);
|
1301
1301
|
}
|
1302
1302
|
|
1303
|
+
[Fact]
|
1304
|
+
public async Task NuGetSourceDoesNotExist()
|
1305
|
+
{
|
1306
|
+
// this test simulates a `NuGet.Config` that points to an internal-only domain that dependabot doesn't have access to
|
1307
|
+
await TestAnalyzeAsync(
|
1308
|
+
extraFiles: [
|
1309
|
+
("NuGet.Config", """
|
1310
|
+
<configuration>
|
1311
|
+
<packageSources>
|
1312
|
+
<clear />
|
1313
|
+
<add key="feed_that_does_not_exist" value="https://this-domain-does-not-exist/nuget/v2" />
|
1314
|
+
</packageSources>
|
1315
|
+
</configuration>
|
1316
|
+
""")
|
1317
|
+
],
|
1318
|
+
discovery: new()
|
1319
|
+
{
|
1320
|
+
Path = "/",
|
1321
|
+
Projects = [
|
1322
|
+
new()
|
1323
|
+
{
|
1324
|
+
FilePath = "./project.csproj",
|
1325
|
+
TargetFrameworks = ["net9.0"],
|
1326
|
+
Dependencies = [
|
1327
|
+
new("Some.Package", "1.0.0", DependencyType.PackageReference),
|
1328
|
+
],
|
1329
|
+
ReferencedProjectPaths = [],
|
1330
|
+
ImportedFiles = [],
|
1331
|
+
AdditionalFiles = [],
|
1332
|
+
}
|
1333
|
+
]
|
1334
|
+
},
|
1335
|
+
dependencyInfo: new()
|
1336
|
+
{
|
1337
|
+
Name = "Some.Package",
|
1338
|
+
Version = "1.0.0",
|
1339
|
+
IgnoredVersions = [],
|
1340
|
+
IsVulnerable = false,
|
1341
|
+
Vulnerabilities = [],
|
1342
|
+
},
|
1343
|
+
expectedResult: new()
|
1344
|
+
{
|
1345
|
+
CanUpdate = false,
|
1346
|
+
UpdatedVersion = "1.0.0",
|
1347
|
+
VersionComesFromMultiDependencyProperty = false,
|
1348
|
+
UpdatedDependencies = [],
|
1349
|
+
}
|
1350
|
+
);
|
1351
|
+
}
|
1352
|
+
|
1303
1353
|
[Fact]
|
1304
1354
|
public void DeserializeDependencyInfo_UnsupportedIgnoredVersionsAreIgnored()
|
1305
1355
|
{
|
@@ -1355,4 +1355,30 @@ public partial class DiscoveryWorkerTests : DiscoveryWorkerTestBase
|
|
1355
1355
|
}
|
1356
1356
|
);
|
1357
1357
|
}
|
1358
|
+
|
1359
|
+
[Fact]
|
1360
|
+
public async Task MissingFileIsReported()
|
1361
|
+
{
|
1362
|
+
await TestDiscoveryAsync(
|
1363
|
+
packages: [],
|
1364
|
+
experimentsManager: new ExperimentsManager() { UseDirectDiscovery = true, InstallDotnetSdks = true },
|
1365
|
+
workspacePath: "",
|
1366
|
+
files: [
|
1367
|
+
("project.csproj", """
|
1368
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
1369
|
+
<Import Project="file-that-does-not-exist.props" />
|
1370
|
+
<PropertyGroup>
|
1371
|
+
<TargetFramework>net8.0</TargetFramework>
|
1372
|
+
</PropertyGroup>
|
1373
|
+
</Project>
|
1374
|
+
""")
|
1375
|
+
],
|
1376
|
+
expectedResult: new()
|
1377
|
+
{
|
1378
|
+
Path = "",
|
1379
|
+
Projects = [],
|
1380
|
+
ErrorRegex = @"file-that-does-not-exist\.props",
|
1381
|
+
}
|
1382
|
+
);
|
1383
|
+
}
|
1358
1384
|
}
|
data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/FrameworkChecker/CompatibilityCheckerFacts.cs
CHANGED
@@ -7,6 +7,8 @@ namespace NuGetUpdater.Core.Test.FrameworkChecker;
|
|
7
7
|
public class CompatibilityCheckerFacts
|
8
8
|
{
|
9
9
|
[Theory]
|
10
|
+
[InlineData("net9.0", "net9.0")]
|
11
|
+
[InlineData("net9.0", "net8.0")]
|
10
12
|
[InlineData("net8.0", "net8.0")]
|
11
13
|
[InlineData("net8.0", "net7.0")]
|
12
14
|
[InlineData("net7.0", "net7.0")]
|
@@ -58,7 +58,7 @@ public class MiscellaneousTests
|
|
58
58
|
public void GetUpdateOperations(WorkspaceDiscoveryResult discovery, (string ProjectPath, string DependencyName)[] expectedUpdateOperations)
|
59
59
|
{
|
60
60
|
var updateOperations = RunWorker.GetUpdateOperations(discovery).ToArray();
|
61
|
-
var actualUpdateOperations = updateOperations.Select(uo => (uo.
|
61
|
+
var actualUpdateOperations = updateOperations.Select(uo => (uo.FilePath, uo.Dependency.Name)).ToArray();
|
62
62
|
Assert.Equal(expectedUpdateOperations, actualUpdateOperations);
|
63
63
|
}
|
64
64
|
|
@@ -94,6 +94,34 @@ public class MiscellaneousTests
|
|
94
94
|
("/src/Common.csproj", "Package.D"),
|
95
95
|
},
|
96
96
|
];
|
97
|
+
|
98
|
+
yield return
|
99
|
+
[
|
100
|
+
new WorkspaceDiscoveryResult()
|
101
|
+
{
|
102
|
+
Path = "",
|
103
|
+
Projects = [],
|
104
|
+
GlobalJson = new()
|
105
|
+
{
|
106
|
+
FilePath = "global.json",
|
107
|
+
Dependencies = [
|
108
|
+
new("Some.MSBuild.Sdk", "1.0.0", DependencyType.MSBuildSdk)
|
109
|
+
]
|
110
|
+
},
|
111
|
+
DotNetToolsJson = new()
|
112
|
+
{
|
113
|
+
FilePath = ".config/dotnet-tools.json",
|
114
|
+
Dependencies = [
|
115
|
+
new("some-tool", "2.0.0", DependencyType.DotNetTool)
|
116
|
+
]
|
117
|
+
}
|
118
|
+
},
|
119
|
+
new (string, string)[]
|
120
|
+
{
|
121
|
+
("/.config/dotnet-tools.json", "some-tool"),
|
122
|
+
("/global.json", "Some.MSBuild.Sdk"),
|
123
|
+
}
|
124
|
+
];
|
97
125
|
}
|
98
126
|
|
99
127
|
public static IEnumerable<object?[]> RequirementsFromIgnoredVersionsData()
|