dependabot-nuget 0.265.0 → 0.267.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/UpdateCommand.cs +6 -6
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +173 -0
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalysisResult.cs +1 -1
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +92 -79
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +21 -8
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/NuGetContext.cs +36 -9
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/Requirement.cs +88 -45
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +33 -16
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +44 -25
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +1 -1
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +9 -0
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/ProjectBuildFile.cs +2 -2
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/MissingFileException.cs +11 -0
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NativeResult.cs +8 -0
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +45 -42
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +19 -1
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +2 -1
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdateOperationResult.cs +5 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +70 -22
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +29 -1
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +6 -2
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +450 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/CompatibilityCheckerTests.cs +23 -0
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/RequirementTests.cs +1 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +2 -0
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +148 -0
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +1 -1
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +17 -22
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestHttpServer.cs +81 -0
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +27 -7
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +32 -0
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +447 -2
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +88 -0
  35. data/lib/dependabot/nuget/analysis/dependency_analysis.rb +3 -0
  36. data/lib/dependabot/nuget/file_fetcher.rb +30 -11
  37. data/lib/dependabot/nuget/file_updater.rb +2 -0
  38. data/lib/dependabot/nuget/metadata_finder.rb +160 -2
  39. data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +3 -0
  40. data/lib/dependabot/nuget/native_helpers.rb +36 -3
  41. data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +1 -0
  42. data/lib/dependabot/nuget/nuget_config_credential_helpers.rb +3 -0
  43. metadata +12 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c8985bae397230599aee116240d6569573ea126c70bc39a37a568935aaf3649
4
- data.tar.gz: b137e9983b1ce14c86235b898a70039c53aadf9eb7a4389b94631bc787ba7914
3
+ metadata.gz: 19fd9d2635d3d1f5737870ebe8bcd155fb5e90557c7eec2b6832233bb0573b29
4
+ data.tar.gz: d1bd4ff99ae3fd8319a796cf04ba3a859c084cd465013cd5a1c8b106969a8183
5
5
  SHA512:
6
- metadata.gz: bbcf0d5509e6bad8ea0af998c7ee6ea6047c13153c4111b2f9e46d568b559bcbe93eb21e8a200ee9deabb4c41bad10e789d236bb6fb30a34ed8c072a47537ced
7
- data.tar.gz: 21ffbb1f7c7ff6a40d8db845b6e175c0f9478d5b99cadd969b127bbed07171b2b120bb3c6a107a1a41d59245906a7276f4006f0cdef4a2f01105d218596bfc6e
6
+ metadata.gz: 4b1c5c0ed9ca379e3c209c21dbc047e7364a9c3f7eda956ebd11a6f0f44b5a3a3e5a7fe9493ccafe82ac98bad132ab2323a56817c2f234c135814282cd229c30
7
+ data.tar.gz: c0f297752cb28d6c32df1261ab10199a5f39e17af23f3c3e46ed76aafd59785e79cd43c81e1a164b8fe92b9f7763f50e3d2c4a8d34c9bb59a4976d0e6eb44be4
@@ -1,6 +1,4 @@
1
- using System;
2
1
  using System.CommandLine;
3
- using System.IO;
4
2
 
5
3
  using NuGetUpdater.Core;
6
4
 
@@ -15,6 +13,7 @@ internal static class UpdateCommand
15
13
  internal static readonly Option<string> PreviousVersionOption = new("--previous-version") { IsRequired = true };
16
14
  internal static readonly Option<bool> IsTransitiveOption = new("--transitive", getDefaultValue: () => false);
17
15
  internal static readonly Option<bool> VerboseOption = new("--verbose", getDefaultValue: () => false);
16
+ internal static readonly Option<string?> ResultOutputPathOption = new("--result-output-path", getDefaultValue: () => null);
18
17
 
19
18
  internal static Command GetCommand(Action<int> setExitCode)
20
19
  {
@@ -26,17 +25,18 @@ internal static class UpdateCommand
26
25
  NewVersionOption,
27
26
  PreviousVersionOption,
28
27
  IsTransitiveOption,
29
- VerboseOption
28
+ VerboseOption,
29
+ ResultOutputPathOption
30
30
  };
31
31
 
32
32
  command.TreatUnmatchedTokensAsErrors = true;
33
33
 
34
- command.SetHandler(async (repoRoot, solutionOrProjectFile, dependencyName, newVersion, previousVersion, isTransitive, verbose) =>
34
+ command.SetHandler(async (repoRoot, solutionOrProjectFile, dependencyName, newVersion, previousVersion, isTransitive, verbose, resultOutputPath) =>
35
35
  {
36
36
  var worker = new UpdaterWorker(new Logger(verbose));
37
- await worker.RunAsync(repoRoot.FullName, solutionOrProjectFile.FullName, dependencyName, previousVersion, newVersion, isTransitive);
37
+ await worker.RunAsync(repoRoot.FullName, solutionOrProjectFile.FullName, dependencyName, previousVersion, newVersion, isTransitive, resultOutputPath);
38
38
  setExitCode(0);
39
- }, RepoRootOption, SolutionOrProjectFileOption, DependencyNameOption, NewVersionOption, PreviousVersionOption, IsTransitiveOption, VerboseOption);
39
+ }, RepoRootOption, SolutionOrProjectFileOption, DependencyNameOption, NewVersionOption, PreviousVersionOption, IsTransitiveOption, VerboseOption, ResultOutputPathOption);
40
40
 
41
41
  return command;
42
42
  }
@@ -134,6 +134,179 @@ public partial class EntryPointTests
134
134
  );
135
135
  }
136
136
 
137
+ [Fact]
138
+ public async Task DotNetToolsJsonCanBeAnalyzed()
139
+ {
140
+ var repoMetadata = XElement.Parse("""<repository type="git" url="https://nuget.example.com/some-global-tool" />""");
141
+ await RunAsync(path =>
142
+ [
143
+ "analyze",
144
+ "--repo-root",
145
+ path,
146
+ "--discovery-file-path",
147
+ Path.Join(path, "discovery.json"),
148
+ "--dependency-file-path",
149
+ Path.Join(path, "some-global-tool.json"),
150
+ "--analysis-folder-path",
151
+ Path.Join(path, AnalyzeWorker.AnalysisDirectoryName),
152
+ "--verbose",
153
+ ],
154
+ packages:
155
+ [
156
+ MockNuGetPackage.CreateDotNetToolPackage("some-global-tool", "1.0.0", "net8.0", additionalMetadata: [repoMetadata]),
157
+ MockNuGetPackage.CreateDotNetToolPackage("some-global-tool", "1.1.0", "net8.0", additionalMetadata: [repoMetadata]),
158
+ ],
159
+ dependencyName: "some-global-tool",
160
+ initialFiles:
161
+ [
162
+ (".config/dotnet-tools.json", """
163
+ {
164
+ "version": 1,
165
+ "isRoot": true,
166
+ "tools": {
167
+ "some-global-tool": {
168
+ "version": "1.0.0",
169
+ "commands": [
170
+ "some-global-tool"
171
+ ]
172
+ }
173
+ }
174
+ }
175
+ """),
176
+ ("discovery.json", """
177
+ {
178
+ "Path": "",
179
+ "IsSuccess": true,
180
+ "Projects": [],
181
+ "DotNetToolsJson": {
182
+ "FilePath": ".config/dotnet-tools.json",
183
+ "IsSuccess": true,
184
+ "Dependencies": [
185
+ {
186
+ "Name": "some-global-tool",
187
+ "Version": "1.0.0",
188
+ "Type": "DotNetTool",
189
+ "EvaluationResult": null,
190
+ "TargetFrameworks": null,
191
+ "IsDevDependency": false,
192
+ "IsDirect": false,
193
+ "IsTransitive": false,
194
+ "IsOverride": false,
195
+ "IsUpdate": false,
196
+ "InfoUrl": null
197
+ }
198
+ ]
199
+ }
200
+ }
201
+ """),
202
+ ("some-global-tool.json", """
203
+ {
204
+ "Name": "some-global-tool",
205
+ "Version": "1.0.0",
206
+ "IsVulnerable": false,
207
+ "IgnoredVersions": [],
208
+ "Vulnerabilities": []
209
+ }
210
+ """),
211
+ ],
212
+ expectedResult: new()
213
+ {
214
+ UpdatedVersion = "1.1.0",
215
+ CanUpdate = true,
216
+ VersionComesFromMultiDependencyProperty = false,
217
+ UpdatedDependencies =
218
+ [
219
+ new Dependency("some-global-tool", "1.1.0", DependencyType.DotNetTool, TargetFrameworks: null, IsDirect: true, InfoUrl: "https://nuget.example.com/some-global-tool")
220
+ ],
221
+ }
222
+ );
223
+ }
224
+
225
+ [Fact]
226
+ public async Task GlobalJsonCanBeAnalyzed()
227
+ {
228
+ var repoMetadata = XElement.Parse("""<repository type="git" url="https://nuget.example.com/some.msbuild.sdk" />""");
229
+ await RunAsync(path =>
230
+ [
231
+ "analyze",
232
+ "--repo-root",
233
+ path,
234
+ "--discovery-file-path",
235
+ Path.Join(path, "discovery.json"),
236
+ "--dependency-file-path",
237
+ Path.Join(path, "Some.MSBuild.Sdk.json"),
238
+ "--analysis-folder-path",
239
+ Path.Join(path, AnalyzeWorker.AnalysisDirectoryName),
240
+ "--verbose",
241
+ ],
242
+ packages:
243
+ [
244
+ MockNuGetPackage.CreateMSBuildSdkPackage("Some.MSBuild.Sdk", "1.0.0", "net8.0", additionalMetadata: [repoMetadata]),
245
+ MockNuGetPackage.CreateMSBuildSdkPackage("Some.MSBuild.Sdk", "1.1.0", "net8.0", additionalMetadata: [repoMetadata]),
246
+ ],
247
+ dependencyName: "Some.MSBuild.Sdk",
248
+ initialFiles:
249
+ [
250
+ ("global.json", """
251
+ {
252
+ "sdk": {
253
+ "version": "8.0.300",
254
+ "rollForward": "latestPatch"
255
+ },
256
+ "msbuild-sdks": {
257
+ "Some.MSBuild.Sdk": "1.0.0"
258
+ }
259
+ }
260
+ """),
261
+ ("discovery.json", """
262
+ {
263
+ "Path": "",
264
+ "IsSuccess": true,
265
+ "Projects": [],
266
+ "GlobalJson": {
267
+ "FilePath": "global.json",
268
+ "IsSuccess": true,
269
+ "Dependencies": [
270
+ {
271
+ "Name": "Some.MSBuild.Sdk",
272
+ "Version": "1.0.0",
273
+ "Type": "MSBuildSdk",
274
+ "EvaluationResult": null,
275
+ "TargetFrameworks": null,
276
+ "IsDevDependency": false,
277
+ "IsDirect": false,
278
+ "IsTransitive": false,
279
+ "IsOverride": false,
280
+ "IsUpdate": false,
281
+ "InfoUrl": null
282
+ }
283
+ ]
284
+ }
285
+ }
286
+ """),
287
+ ("Some.MSBuild.Sdk.json", """
288
+ {
289
+ "Name": "Some.MSBuild.Sdk",
290
+ "Version": "1.0.0",
291
+ "IsVulnerable": false,
292
+ "IgnoredVersions": [],
293
+ "Vulnerabilities": []
294
+ }
295
+ """),
296
+ ],
297
+ expectedResult: new()
298
+ {
299
+ UpdatedVersion = "1.1.0",
300
+ CanUpdate = true,
301
+ VersionComesFromMultiDependencyProperty = false,
302
+ UpdatedDependencies =
303
+ [
304
+ new Dependency("Some.MSBuild.Sdk", "1.1.0", DependencyType.MSBuildSdk, TargetFrameworks: null, IsDirect: true, InfoUrl: "https://nuget.example.com/some.msbuild.sdk")
305
+ ],
306
+ }
307
+ );
308
+ }
309
+
137
310
  private static async Task RunAsync(Func<string, string[]> getArgs, string dependencyName, TestFile[] initialFiles, ExpectedAnalysisResult expectedResult, MockNuGetPackage[]? packages = null)
138
311
  {
139
312
  var actualResult = await RunAnalyzerAsync(dependencyName, initialFiles, async path =>
@@ -2,7 +2,7 @@ using System.Collections.Immutable;
2
2
 
3
3
  namespace NuGetUpdater.Core.Analyze;
4
4
 
5
- public record AnalysisResult
5
+ public record AnalysisResult : NativeResult
6
6
  {
7
7
  public required string UpdatedVersion { get; init; }
8
8
  public bool CanUpdate { get; init; }
@@ -1,8 +1,8 @@
1
1
  using System.Collections.Immutable;
2
+ using System.Net;
2
3
  using System.Text.Json;
3
4
  using System.Text.Json.Serialization;
4
5
 
5
- using NuGet.Configuration;
6
6
  using NuGet.Frameworks;
7
7
  using NuGet.Versioning;
8
8
 
@@ -51,76 +51,110 @@ public partial class AnalyzeWorker
51
51
  => p.Dependencies.Where(d => !d.IsTransitive &&
52
52
  d.EvaluationResult?.RootPropertyName is not null)
53
53
  ).ToImmutableArray();
54
+ var dotnetToolsHasDependency = discovery.DotNetToolsJson?.Dependencies.Any(d => d.Name.Equals(dependencyInfo.Name, StringComparison.OrdinalIgnoreCase)) == true;
55
+ var globalJsonHasDependency = discovery.GlobalJson?.Dependencies.Any(d => d.Name.Equals(dependencyInfo.Name, StringComparison.OrdinalIgnoreCase)) == true;
54
56
 
55
57
  bool usesMultiDependencyProperty = false;
56
58
  NuGetVersion? updatedVersion = null;
57
59
  ImmutableArray<Dependency> updatedDependencies = [];
58
60
 
59
- bool isUpdateNecessary = IsUpdateNecessary(dependencyInfo, projectsWithDependency);
60
- if (isUpdateNecessary)
61
+ bool isProjectUpdateNecessary = IsUpdateNecessary(dependencyInfo, projectsWithDependency);
62
+ var isUpdateNecessary = isProjectUpdateNecessary || dotnetToolsHasDependency || globalJsonHasDependency;
63
+ using var nugetContext = new NuGetContext(startingDirectory);
64
+ AnalysisResult result;
65
+ try
61
66
  {
62
- var nugetContext = new NuGetContext(startingDirectory);
63
- if (!Directory.Exists(nugetContext.TempPackageDirectory))
67
+ if (isUpdateNecessary)
64
68
  {
65
- Directory.CreateDirectory(nugetContext.TempPackageDirectory);
66
- }
67
-
68
- _logger.Log($" Determining multi-dependency property.");
69
- var multiDependencies = DetermineMultiDependencyDetails(
70
- discovery,
71
- dependencyInfo.Name,
72
- propertyBasedDependencies);
73
-
74
- usesMultiDependencyProperty = multiDependencies.Any(md => md.DependencyNames.Count > 1);
75
- var dependenciesToUpdate = usesMultiDependencyProperty
76
- ? multiDependencies
77
- .SelectMany(md => md.DependencyNames)
78
- .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
79
- : [dependencyInfo.Name];
80
- var applicableTargetFrameworks = usesMultiDependencyProperty
81
- ? multiDependencies
82
- .SelectMany(md => md.TargetFrameworks)
83
- .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
84
- .Select(NuGetFramework.Parse)
85
- .ToImmutableArray()
86
- : projectFrameworks;
87
-
88
- _logger.Log($" Finding updated version.");
89
- updatedVersion = await FindUpdatedVersionAsync(
90
- startingDirectory,
91
- dependencyInfo,
92
- dependenciesToUpdate,
93
- applicableTargetFrameworks,
94
- nugetContext,
95
- _logger,
96
- CancellationToken.None);
97
-
98
- _logger.Log($" Finding updated peer dependencies.");
99
- updatedDependencies = updatedVersion is not null
100
- ? await FindUpdatedDependenciesAsync(
101
- repoRoot,
69
+ _logger.Log($" Determining multi-dependency property.");
70
+ var multiDependencies = DetermineMultiDependencyDetails(
102
71
  discovery,
72
+ dependencyInfo.Name,
73
+ propertyBasedDependencies);
74
+
75
+ usesMultiDependencyProperty = multiDependencies.Any(md => md.DependencyNames.Count > 1);
76
+ var dependenciesToUpdate = usesMultiDependencyProperty
77
+ ? multiDependencies
78
+ .SelectMany(md => md.DependencyNames)
79
+ .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
80
+ : [dependencyInfo.Name];
81
+ var applicableTargetFrameworks = usesMultiDependencyProperty
82
+ ? multiDependencies
83
+ .SelectMany(md => md.TargetFrameworks)
84
+ .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
85
+ .Select(NuGetFramework.Parse)
86
+ .ToImmutableArray()
87
+ : projectFrameworks;
88
+
89
+ _logger.Log($" Finding updated version.");
90
+ updatedVersion = await FindUpdatedVersionAsync(
91
+ startingDirectory,
92
+ dependencyInfo,
103
93
  dependenciesToUpdate,
104
- updatedVersion,
94
+ applicableTargetFrameworks,
105
95
  nugetContext,
106
96
  _logger,
107
- CancellationToken.None)
108
- : [];
109
-
110
- //TODO: At this point we should add the peer dependencies to a queue where
111
- // we will analyze them one by one to see if they themselves are part of a
112
- // multi-dependency property. Basically looping this if-body until we have
113
- // emptied the queue and have a complete list of updated dependencies. We
114
- // should track the dependenciesToUpdate as they have already been analyzed.
115
- }
97
+ CancellationToken.None);
98
+
99
+ _logger.Log($" Finding updated peer dependencies.");
100
+ if (updatedVersion is null)
101
+ {
102
+ updatedDependencies = [];
103
+ }
104
+ else if (isProjectUpdateNecessary)
105
+ {
106
+ updatedDependencies = await FindUpdatedDependenciesAsync(
107
+ repoRoot,
108
+ discovery,
109
+ dependenciesToUpdate,
110
+ updatedVersion,
111
+ nugetContext,
112
+ _logger,
113
+ CancellationToken.None);
114
+ }
115
+ else if (dotnetToolsHasDependency)
116
+ {
117
+ var infoUrl = await nugetContext.GetPackageInfoUrlAsync(dependencyInfo.Name, updatedVersion.ToNormalizedString(), CancellationToken.None);
118
+ updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.DotNetTool, IsDirect: true, InfoUrl: infoUrl)];
119
+ }
120
+ else if (globalJsonHasDependency)
121
+ {
122
+ var infoUrl = await nugetContext.GetPackageInfoUrlAsync(dependencyInfo.Name, updatedVersion.ToNormalizedString(), CancellationToken.None);
123
+ updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.MSBuildSdk, IsDirect: true, InfoUrl: infoUrl)];
124
+ }
125
+ else
126
+ {
127
+ throw new InvalidOperationException("Unreachable.");
128
+ }
129
+
130
+ //TODO: At this point we should add the peer dependencies to a queue where
131
+ // we will analyze them one by one to see if they themselves are part of a
132
+ // multi-dependency property. Basically looping this if-body until we have
133
+ // emptied the queue and have a complete list of updated dependencies. We
134
+ // should track the dependenciesToUpdate as they have already been analyzed.
135
+ }
116
136
 
117
- var result = new AnalysisResult
137
+ result = new AnalysisResult
138
+ {
139
+ UpdatedVersion = updatedVersion?.ToNormalizedString() ?? dependencyInfo.Version,
140
+ CanUpdate = updatedVersion is not null,
141
+ VersionComesFromMultiDependencyProperty = usesMultiDependencyProperty,
142
+ UpdatedDependencies = updatedDependencies,
143
+ };
144
+ }
145
+ catch (HttpRequestException ex)
146
+ when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
118
147
  {
119
- UpdatedVersion = updatedVersion?.ToNormalizedString() ?? dependencyInfo.Version,
120
- CanUpdate = updatedVersion is not null,
121
- VersionComesFromMultiDependencyProperty = usesMultiDependencyProperty,
122
- UpdatedDependencies = updatedDependencies,
123
- };
148
+ // TODO: consolidate this error handling between AnalyzeWorker, DiscoveryWorker, and UpdateWorker
149
+ result = new AnalysisResult
150
+ {
151
+ ErrorType = ErrorType.AuthenticationFailure,
152
+ ErrorDetails = "(" + string.Join("|", nugetContext.PackageSources.Select(s => s.Source)) + ")",
153
+ UpdatedVersion = string.Empty,
154
+ CanUpdate = false,
155
+ UpdatedDependencies = [],
156
+ };
157
+ }
124
158
 
125
159
  await WriteResultsAsync(analysisDirectory, dependencyInfo.Name, result, _logger);
126
160
 
@@ -314,27 +348,6 @@ public partial class AnalyzeWorker
314
348
  return true;
315
349
  }
316
350
 
317
- internal static async Task<ImmutableDictionary<NuGetFramework, ImmutableArray<Dependency>>> GetDependenciesAsync(
318
- string workspacePath,
319
- string projectPath,
320
- IEnumerable<NuGetFramework> frameworks,
321
- Dependency package,
322
- Logger logger)
323
- {
324
- var result = ImmutableDictionary.CreateBuilder<NuGetFramework, ImmutableArray<Dependency>>();
325
- foreach (var framework in frameworks)
326
- {
327
- var dependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(
328
- workspacePath,
329
- projectPath,
330
- framework.ToString(),
331
- [package],
332
- logger);
333
- result.Add(framework, [.. dependencies]);
334
- }
335
- return result.ToImmutable();
336
- }
337
-
338
351
  internal static async Task<ImmutableArray<Dependency>> FindUpdatedDependenciesAsync(
339
352
  string repoRoot,
340
353
  WorkspaceDiscoveryResult discovery,
@@ -54,6 +54,11 @@ internal static class CompatibilityChecker
54
54
 
55
55
  var compatibilityService = new FrameworkCompatibilityService();
56
56
  var compatibleFrameworks = compatibilityService.GetCompatibleFrameworks(packageFrameworks);
57
+ var packageSupportsAny = compatibleFrameworks.Any(f => f.IsAny);
58
+ if (packageSupportsAny)
59
+ {
60
+ return true;
61
+ }
57
62
 
58
63
  var incompatibleFrameworks = projectFrameworks.Where(f => !compatibleFrameworks.Contains(f)).ToArray();
59
64
  if (incompatibleFrameworks.Length > 0)
@@ -141,15 +146,23 @@ internal static class CompatibilityChecker
141
146
  throw new NotSupportedException($"Failed to get FindPackageByIdResource for {source.SourceUri}");
142
147
  }
143
148
 
144
- var exists = await feed.DoesPackageExistAsync(
145
- package.Id,
146
- package.Version,
147
- context.SourceCacheContext,
148
- NullLogger.Instance,
149
- cancellationToken);
150
-
151
- if (!exists)
149
+ try
150
+ {
151
+ // a non-compliant v2 API returning 404 can cause this to throw
152
+ var exists = await feed.DoesPackageExistAsync(
153
+ package.Id,
154
+ package.Version,
155
+ context.SourceCacheContext,
156
+ NullLogger.Instance,
157
+ cancellationToken);
158
+ if (!exists)
159
+ {
160
+ continue;
161
+ }
162
+ }
163
+ catch (FatalProtocolException)
152
164
  {
165
+ // if anything goes wrong here, the package source obviously doesn't contain the requested package
153
166
  continue;
154
167
  }
155
168
 
@@ -37,16 +37,34 @@ internal record NuGetContext : IDisposable
37
37
  .Where(p => p.IsEnabled)
38
38
  .ToImmutableArray();
39
39
  Logger = logger ?? NullLogger.Instance;
40
- TempPackageDirectory = Path.Combine(Path.GetTempPath(), ".dependabot", "packages");
40
+ TempPackageDirectory = Path.Combine(Path.GetTempPath(), $"dependabot-packages_{Guid.NewGuid():d}");
41
+ Directory.CreateDirectory(TempPackageDirectory);
41
42
  }
42
43
 
43
44
  public void Dispose()
44
45
  {
45
46
  SourceCacheContext.Dispose();
47
+ if (Directory.Exists(TempPackageDirectory))
48
+ {
49
+ try
50
+ {
51
+ Directory.Delete(TempPackageDirectory, recursive: true);
52
+ }
53
+ catch
54
+ {
55
+ }
56
+ }
46
57
  }
47
58
 
48
59
  private readonly Dictionary<PackageIdentity, string?> _packageInfoUrlCache = new();
49
60
 
61
+ public static string[] GetPackageSourceUrls(string currentDirectory)
62
+ {
63
+ using var context = new NuGetContext(currentDirectory);
64
+ var sourceUrls = context.PackageSources.Select(s => s.Source).ToArray();
65
+ return sourceUrls;
66
+ }
67
+
50
68
  public async Task<string?> GetPackageInfoUrlAsync(string packageId, string packageVersion, CancellationToken cancellationToken)
51
69
  {
52
70
  var packageIdentity = new PackageIdentity(packageId, NuGetVersion.Parse(packageVersion));
@@ -86,15 +104,24 @@ internal record NuGetContext : IDisposable
86
104
  continue;
87
105
  }
88
106
 
89
- var existsInFeed = await feed.Exists(
90
- packageIdentity,
91
- includeUnlisted: false,
92
- SourceCacheContext,
93
- NullLogger.Instance,
94
- cancellationToken);
95
- if (!existsInFeed)
107
+ try
108
+ {
109
+ // a non-compliant v2 API returning 404 can cause this to throw
110
+ var existsInFeed = await feed.Exists(
111
+ packageIdentity,
112
+ includeUnlisted: false,
113
+ SourceCacheContext,
114
+ NullLogger.Instance,
115
+ cancellationToken);
116
+ if (!existsInFeed)
117
+ {
118
+ message.AppendLine($" package {packageIdentity} does not exist in {source.Name}");
119
+ continue;
120
+ }
121
+ }
122
+ catch (FatalProtocolException)
96
123
  {
97
- message.AppendLine($" package {packageIdentity} does not exist in {source.Name}");
124
+ // if anything goes wrong here, the package source obviously doesn't contain the requested package
98
125
  continue;
99
126
  }
100
127