dependabot-nuget 0.277.0 → 0.279.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/build +1 -1
  3. data/helpers/lib/NuGetUpdater/.editorconfig +1 -0
  4. data/helpers/lib/NuGetUpdater/Directory.Build.props +1 -0
  5. data/helpers/lib/NuGetUpdater/Directory.Common.props +1 -1
  6. data/helpers/lib/NuGetUpdater/Directory.Packages.props +6 -1
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +42 -0
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Program.cs +1 -0
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Run.cs +132 -0
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +2 -3
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +94 -85
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyFinder.cs +2 -2
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/Requirement.cs +2 -2
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +47 -41
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +2 -1
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/AllowedUpdate.cs +6 -0
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/CreatePullRequest.cs +18 -0
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyFile.cs +18 -0
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyFileNotFound.cs +6 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/IncrementMetric.cs +7 -0
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Job.cs +49 -0
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/JobErrorBase.cs +11 -0
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/JobFile.cs +6 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/JobSource.cs +11 -0
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/MarkAsProcessed.cs +9 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/PrivateSourceAuthenticationFailure.cs +6 -0
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/ReportedDependency.cs +16 -0
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/ReportedRequirement.cs +9 -0
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/RequirementSource.cs +7 -0
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/UnknownError.cs +6 -0
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/UpdatedDependencyList.cs +7 -0
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/HttpApiHandler.cs +64 -0
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/IApiHandler.cs +12 -0
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunResult.cs +13 -0
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +328 -0
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +28 -0
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +1 -1
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +53 -37
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +5 -5
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -1
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +34 -0
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProcessExtensions.cs +2 -4
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/RequirementTests.cs +4 -1
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +10 -1
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +315 -0
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +60 -0
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/TestApiHandler.cs +41 -0
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatedDependencyListTests.cs +69 -0
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +8 -8
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +10 -1
  51. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/PathHelperTests.cs +22 -0
  52. data/helpers/lib/NuGetUpdater/global.json +1 -1
  53. data/lib/dependabot/nuget/file_fetcher.rb +17 -0
  54. data/lib/dependabot/nuget/file_updater.rb +5 -1
  55. data/lib/dependabot/nuget/native_helpers.rb +4 -1
  56. data/lib/dependabot/nuget/requirement.rb +2 -0
  57. data/lib/dependabot/nuget/update_checker/repository_finder.rb +26 -2
  58. metadata +33 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 492a5ffafd58adff4054fe829df3b316905a6c8bcfad5f291f9caa7653118a43
4
- data.tar.gz: 75fbd529bc36ec77ae4b849c62a612272586803cc7792af3b5ce1bdd76bd592c
3
+ metadata.gz: 644fb3ec407649eb15e5e9ab7be78a85f8f03900adcc93819e3be781610cf78e
4
+ data.tar.gz: 408ef4e6a5d517d159256429a2d68d61bc0e0188e3f0c13a4c0aa6b00b55e74b
5
5
  SHA512:
6
- metadata.gz: d4ebd69a7d512170e67677cc9a92bb1a791d92fc8591cf05d405da86449d523796cb0074afeb856ead16a074926ebca38d0173b7265cdc0941f271ecb1e8a575
7
- data.tar.gz: 1fe2bb3b9f317dfd931ec36efb5b0faa6689860c40595cec827c5f3a3666789a793a2350ed1f0f72612539fa9d1641858b693d115579166fd9c5f36c698976ce
6
+ metadata.gz: 25125733df999707391798277975f970cfcf4bd87809165612d600a245d758e9bad553e046c8a0ff566446a90426c6719fedffa3a82139212c6f106de412bea7
7
+ data.tar.gz: 5db427ffb67c418e0f99dcc3f83a5f320a7fc3aaff177425a5c32d9b48b3296495c9fdc5f0fbd0959c2da0cc0b35132a532b1ec83af494950df15d3fa076435e
data/helpers/build CHANGED
@@ -32,7 +32,7 @@ cd "$install_dir/lib/NuGetUpdater/NuGetUpdater.Cli"
32
32
  dotnet publish \
33
33
  --configuration Release \
34
34
  --output "$install_dir/NuGetUpdater" \
35
- --framework net8.0 \
35
+ --framework net9.0 \
36
36
  --runtime "$os-$arch"
37
37
  dotnet clean
38
38
 
@@ -20,6 +20,7 @@ tab_width = 4
20
20
 
21
21
  # New line preferences
22
22
  insert_final_newline = true
23
+ end_of_line = lf
23
24
 
24
25
  #### .NET Coding Conventions ####
25
26
  [*.{cs,vb}]
@@ -1,6 +1,7 @@
1
1
  <Project>
2
2
 
3
3
  <PropertyGroup>
4
+ <CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
4
5
  <NoWarn>$(NoWarn);NU1701</NoWarn>
5
6
  <Nullable>enable</Nullable>
6
7
  </PropertyGroup>
@@ -9,7 +9,7 @@
9
9
  NuGetUpdater\NuGetUpdater.Core\FrameworkChecker\SupportedFrameworks.cs
10
10
  2. Update tests as needed at `NuGetUpdater\NuGetUpdater.Core.Test\FrameworkChecker\CompatibilityCheckerFacts.cs`
11
11
  -->
12
- <CommonTargetFramework>net8.0</CommonTargetFramework>
12
+ <CommonTargetFramework>net9.0</CommonTargetFramework>
13
13
  <ImplicitUsings>enable</ImplicitUsings>
14
14
  <UseArtifactsOutput>true</UseArtifactsOutput>
15
15
  <ArtifactsPath>$(MSBuildThisFileDirectory)artifacts</ArtifactsPath>
@@ -7,7 +7,7 @@
7
7
  <ItemGroup>
8
8
  <PackageVersion Include="DiffPlex" Version="1.7.1" />
9
9
 
10
- <PackageVersion Include="GuiLabs.Language.Xml" Version="1.2.60" />
10
+ <PackageVersion Include="GuiLabs.Language.Xml" Version="1.2.93" />
11
11
 
12
12
  <PackageVersion Include="Microsoft.Build.Locator" Version="1.6.1" />
13
13
  <PackageVersion Include="Microsoft.Build" Version="17.5.0" ExcludeAssets="Runtime" PrivateAssets="All" />
@@ -20,6 +20,11 @@
20
20
  <PackageVersion Include="NuGet.Core" Version="2.14.0-rtm-832" Aliases="CoreV2" />
21
21
 
22
22
  <PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
23
+ <PackageVersion Include="System.Net.Http" Version="4.3.4" />
24
+ <PackageVersion Include="System.Formats.Asn1" Version="8.0.1" />
25
+ <PackageVersion Include="System.Security.Cryptography.Pkcs" Version="8.0.0" />
26
+ <PackageVersion Include="System.Text.Json" Version="8.0.4" />
27
+ <PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
23
28
 
24
29
  <PackageVersion Include="xunit" Version="2.4.2" />
25
30
  <PackageVersion Include="xunit.runner.visualstudio" Version="2.4.5" />
@@ -0,0 +1,42 @@
1
+ using System.CommandLine;
2
+
3
+ using NuGetUpdater.Core;
4
+ using NuGetUpdater.Core.Run;
5
+
6
+ namespace NuGetUpdater.Cli.Commands;
7
+
8
+ internal static class RunCommand
9
+ {
10
+ internal static readonly Option<FileInfo> JobPathOption = new("--job-path") { IsRequired = true };
11
+ internal static readonly Option<DirectoryInfo> RepoContentsPathOption = new("--repo-contents-path") { IsRequired = true };
12
+ internal static readonly Option<Uri> ApiUrlOption = new("--api-url") { IsRequired = true };
13
+ internal static readonly Option<string> JobIdOption = new("--job-id") { IsRequired = true };
14
+ internal static readonly Option<FileInfo> OutputPathOption = new("--output-path") { IsRequired = true };
15
+ internal static readonly Option<string> BaseCommitShaOption = new("--base-commit-sha") { IsRequired = true };
16
+ internal static readonly Option<bool> VerboseOption = new("--verbose", getDefaultValue: () => false);
17
+
18
+ internal static Command GetCommand(Action<int> setExitCode)
19
+ {
20
+ Command command = new("run", "Runs a full dependabot job.")
21
+ {
22
+ JobPathOption,
23
+ RepoContentsPathOption,
24
+ ApiUrlOption,
25
+ JobIdOption,
26
+ OutputPathOption,
27
+ BaseCommitShaOption,
28
+ VerboseOption
29
+ };
30
+
31
+ command.TreatUnmatchedTokensAsErrors = true;
32
+
33
+ command.SetHandler(async (jobPath, repoContentsPath, apiUrl, jobId, outputPath, baseCommitSha, verbose) =>
34
+ {
35
+ var apiHandler = new HttpApiHandler(apiUrl.ToString(), jobId);
36
+ var worker = new RunWorker(apiHandler, new Logger(verbose));
37
+ await worker.RunAsync(jobPath, repoContentsPath, baseCommitSha, outputPath);
38
+ }, JobPathOption, RepoContentsPathOption, ApiUrlOption, JobIdOption, OutputPathOption, BaseCommitShaOption, VerboseOption);
39
+
40
+ return command;
41
+ }
42
+ }
@@ -17,6 +17,7 @@ internal sealed class Program
17
17
  DiscoverCommand.GetCommand(setExitCode),
18
18
  AnalyzeCommand.GetCommand(setExitCode),
19
19
  UpdateCommand.GetCommand(setExitCode),
20
+ RunCommand.GetCommand(setExitCode),
20
21
  };
21
22
  command.TreatUnmatchedTokensAsErrors = true;
22
23
 
@@ -0,0 +1,132 @@
1
+ using System.Text;
2
+ using System.Text.Json;
3
+
4
+ using NuGetUpdater.Core.Run;
5
+ using NuGetUpdater.Core.Run.ApiModel;
6
+ using NuGetUpdater.Core.Test;
7
+ using NuGetUpdater.Core.Test.Update;
8
+
9
+ using Xunit;
10
+
11
+ namespace NuGetUpdater.Cli.Test;
12
+
13
+ using TestFile = (string Path, string Content);
14
+
15
+ public partial class EntryPointTests
16
+ {
17
+ public class Run
18
+ {
19
+ [Fact]
20
+ public async Task Run_Simple()
21
+ {
22
+ // verify we can pass command line arguments and hit the appropriate URLs
23
+ await RunAsync(
24
+ packages:
25
+ [
26
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0"),
27
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.1", "net8.0"),
28
+ ],
29
+ files:
30
+ [
31
+ ("src/project.csproj", """
32
+ <Project Sdk="Microsoft.NET.Sdk">
33
+ <PropertyGroup>
34
+ <TargetFramework>net8.0</TargetFramework>
35
+ </PropertyGroup>
36
+ <ItemGroup>
37
+ <PackageReference Include="Some.Package" Version="1.0.0" />
38
+ </ItemGroup>
39
+ </Project>
40
+ """)
41
+ ],
42
+ job: new Job()
43
+ {
44
+ PackageManager = "nuget",
45
+ AllowedUpdates = [
46
+ new()
47
+ {
48
+ UpdateType = "all"
49
+ }
50
+ ],
51
+ Source = new()
52
+ {
53
+ Provider = "github",
54
+ Repo = "test",
55
+ Directory = "src",
56
+ }
57
+ },
58
+ expectedUrls:
59
+ [
60
+ "/update_jobs/TEST-ID/update_dependency_list",
61
+ "/update_jobs/TEST-ID/increment_metric",
62
+ "/update_jobs/TEST-ID/create_pull_request",
63
+ "/update_jobs/TEST-ID/mark_as_processed",
64
+ ]
65
+ );
66
+ }
67
+
68
+ private static async Task RunAsync(TestFile[] files, Job job, string[] expectedUrls, MockNuGetPackage[]? packages = null)
69
+ {
70
+ using var tempDirectory = new TemporaryDirectory();
71
+
72
+ // write test files
73
+ foreach (var testFile in files)
74
+ {
75
+ var fullPath = Path.Join(tempDirectory.DirectoryPath, testFile.Path);
76
+ var directory = Path.GetDirectoryName(fullPath)!;
77
+ Directory.CreateDirectory(directory);
78
+ await File.WriteAllTextAsync(fullPath, testFile.Content);
79
+ }
80
+
81
+ // write job file
82
+ var jobPath = Path.Combine(tempDirectory.DirectoryPath, "job.json");
83
+ await File.WriteAllTextAsync(jobPath, JsonSerializer.Serialize(new { Job = job }, RunWorker.SerializerOptions));
84
+
85
+ // save packages
86
+ await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(packages, tempDirectory.DirectoryPath);
87
+
88
+ var actualUrls = new List<string>();
89
+ using var http = TestHttpServer.CreateTestStringServer(url =>
90
+ {
91
+ actualUrls.Add(new Uri(url).PathAndQuery);
92
+ return (200, "ok");
93
+ });
94
+ var args = new List<string>()
95
+ {
96
+ "run",
97
+ "--job-path",
98
+ jobPath,
99
+ "--repo-contents-path",
100
+ tempDirectory.DirectoryPath,
101
+ "--api-url",
102
+ http.BaseUrl,
103
+ "--job-id",
104
+ "TEST-ID",
105
+ "--output-path",
106
+ Path.Combine(tempDirectory.DirectoryPath, "output.json"),
107
+ "--base-commit-sha",
108
+ "BASE-COMMIT-SHA",
109
+ "--verbose"
110
+ };
111
+
112
+ var output = new StringBuilder();
113
+ // redirect stdout
114
+ var originalOut = Console.Out;
115
+ Console.SetOut(new StringWriter(output));
116
+ int result = -1;
117
+ try
118
+ {
119
+ result = await Program.Main(args.ToArray());
120
+ }
121
+ catch
122
+ {
123
+ // restore stdout
124
+ Console.SetOut(originalOut);
125
+ throw;
126
+ }
127
+
128
+ Assert.True(result == 0, output.ToString());
129
+ Assert.Equal(expectedUrls, actualUrls);
130
+ }
131
+ }
132
+ }
@@ -352,8 +352,7 @@ public partial class EntryPointTests
352
352
  </Project>
353
353
  """);
354
354
  var executableName = Path.Join(Path.GetDirectoryName(GetType().Assembly.Location), "NuGetUpdater.Cli.dll");
355
- var executableArgs = string.Join(" ",
356
- [
355
+ IEnumerable<string> executableArgs = [
357
356
  executableName,
358
357
  "update",
359
358
  "--repo-root",
@@ -367,7 +366,7 @@ public partial class EntryPointTests
367
366
  "--previous-version",
368
367
  "7.0.1",
369
368
  "--verbose"
370
- ]);
369
+ ];
371
370
 
372
371
  // verify base run
373
372
  var workingDirectory = tempDir.DirectoryPath;
@@ -31,8 +31,34 @@ public partial class AnalyzeWorker
31
31
 
32
32
  public async Task RunAsync(string repoRoot, string discoveryPath, string dependencyPath, string analysisDirectory)
33
33
  {
34
+ AnalysisResult analysisResult;
34
35
  var discovery = await DeserializeJsonFileAsync<WorkspaceDiscoveryResult>(discoveryPath, nameof(WorkspaceDiscoveryResult));
35
36
  var dependencyInfo = await DeserializeJsonFileAsync<DependencyInfo>(dependencyPath, nameof(DependencyInfo));
37
+
38
+ try
39
+ {
40
+ analysisResult = await RunAsync(repoRoot, discovery, dependencyInfo);
41
+ }
42
+ catch (HttpRequestException ex)
43
+ when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
44
+ {
45
+ var localPath = PathHelper.JoinPath(repoRoot, discovery.Path);
46
+ var nugetContext = new NuGetContext(localPath);
47
+ analysisResult = new AnalysisResult
48
+ {
49
+ ErrorType = ErrorType.AuthenticationFailure,
50
+ ErrorDetails = "(" + string.Join("|", nugetContext.PackageSources.Select(s => s.Source)) + ")",
51
+ UpdatedVersion = string.Empty,
52
+ CanUpdate = false,
53
+ UpdatedDependencies = [],
54
+ };
55
+ }
56
+
57
+ await WriteResultsAsync(analysisDirectory, dependencyInfo.Name, analysisResult, _logger);
58
+ }
59
+
60
+ public async Task<AnalysisResult> RunAsync(string repoRoot, WorkspaceDiscoveryResult discovery, DependencyInfo dependencyInfo)
61
+ {
36
62
  var startingDirectory = PathHelper.JoinPath(repoRoot, discovery.Path);
37
63
 
38
64
  _logger.Log($"Starting analysis of {dependencyInfo.Name}...");
@@ -61,104 +87,87 @@ public partial class AnalyzeWorker
61
87
  bool isProjectUpdateNecessary = IsUpdateNecessary(dependencyInfo, projectsWithDependency);
62
88
  var isUpdateNecessary = isProjectUpdateNecessary || dotnetToolsHasDependency || globalJsonHasDependency;
63
89
  using var nugetContext = new NuGetContext(startingDirectory);
64
- AnalysisResult result;
65
- try
90
+ AnalysisResult analysisResult;
91
+ if (isUpdateNecessary)
66
92
  {
67
- if (isUpdateNecessary)
93
+ _logger.Log($" Determining multi-dependency property.");
94
+ var multiDependencies = DetermineMultiDependencyDetails(
95
+ discovery,
96
+ dependencyInfo.Name,
97
+ propertyBasedDependencies);
98
+
99
+ usesMultiDependencyProperty = multiDependencies.Any(md => md.DependencyNames.Count > 1);
100
+ var dependenciesToUpdate = usesMultiDependencyProperty
101
+ ? multiDependencies
102
+ .SelectMany(md => md.DependencyNames)
103
+ .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
104
+ : [dependencyInfo.Name];
105
+ var applicableTargetFrameworks = usesMultiDependencyProperty
106
+ ? multiDependencies
107
+ .SelectMany(md => md.TargetFrameworks)
108
+ .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
109
+ .Select(NuGetFramework.Parse)
110
+ .ToImmutableArray()
111
+ : projectFrameworks;
112
+
113
+ _logger.Log($" Finding updated version.");
114
+ updatedVersion = await FindUpdatedVersionAsync(
115
+ startingDirectory,
116
+ dependencyInfo,
117
+ dependenciesToUpdate,
118
+ applicableTargetFrameworks,
119
+ nugetContext,
120
+ _logger,
121
+ CancellationToken.None);
122
+
123
+ _logger.Log($" Finding updated peer dependencies.");
124
+ if (updatedVersion is null)
68
125
  {
69
- _logger.Log($" Determining multi-dependency property.");
70
- var multiDependencies = DetermineMultiDependencyDetails(
126
+ updatedDependencies = [];
127
+ }
128
+ else if (isProjectUpdateNecessary)
129
+ {
130
+ updatedDependencies = await FindUpdatedDependenciesAsync(
131
+ repoRoot,
71
132
  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,
93
133
  dependenciesToUpdate,
94
- applicableTargetFrameworks,
134
+ updatedVersion,
95
135
  nugetContext,
96
136
  _logger,
97
137
  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
138
  }
136
-
137
- result = new AnalysisResult
139
+ else if (dotnetToolsHasDependency)
138
140
  {
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)
147
- {
148
- // TODO: consolidate this error handling between AnalyzeWorker, DiscoveryWorker, and UpdateWorker
149
- result = new AnalysisResult
141
+ var infoUrl = await nugetContext.GetPackageInfoUrlAsync(dependencyInfo.Name, updatedVersion.ToNormalizedString(), CancellationToken.None);
142
+ updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.DotNetTool, IsDirect: true, InfoUrl: infoUrl)];
143
+ }
144
+ else if (globalJsonHasDependency)
150
145
  {
151
- ErrorType = ErrorType.AuthenticationFailure,
152
- ErrorDetails = "(" + string.Join("|", nugetContext.PackageSources.Select(s => s.Source)) + ")",
153
- UpdatedVersion = string.Empty,
154
- CanUpdate = false,
155
- UpdatedDependencies = [],
156
- };
146
+ var infoUrl = await nugetContext.GetPackageInfoUrlAsync(dependencyInfo.Name, updatedVersion.ToNormalizedString(), CancellationToken.None);
147
+ updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.MSBuildSdk, IsDirect: true, InfoUrl: infoUrl)];
148
+ }
149
+ else
150
+ {
151
+ throw new InvalidOperationException("Unreachable.");
152
+ }
153
+
154
+ //TODO: At this point we should add the peer dependencies to a queue where
155
+ // we will analyze them one by one to see if they themselves are part of a
156
+ // multi-dependency property. Basically looping this if-body until we have
157
+ // emptied the queue and have a complete list of updated dependencies. We
158
+ // should track the dependenciesToUpdate as they have already been analyzed.
157
159
  }
158
160
 
159
- await WriteResultsAsync(analysisDirectory, dependencyInfo.Name, result, _logger);
161
+ analysisResult = new AnalysisResult
162
+ {
163
+ UpdatedVersion = updatedVersion?.ToNormalizedString() ?? dependencyInfo.Version,
164
+ CanUpdate = updatedVersion is not null,
165
+ VersionComesFromMultiDependencyProperty = usesMultiDependencyProperty,
166
+ UpdatedDependencies = updatedDependencies,
167
+ };
160
168
 
161
169
  _logger.Log($"Analysis complete.");
170
+ return analysisResult;
162
171
  }
163
172
 
164
173
  private static bool IsUpdateNecessary(DependencyInfo dependencyInfo, ImmutableArray<ProjectDiscoveryResult> projectsWithDependency)
@@ -393,7 +402,7 @@ public partial class AnalyzeWorker
393
402
 
394
403
  // Create distinct list of dependencies taking the highest version of each
395
404
  var dependencyResult = await DependencyFinder.GetDependenciesAsync(
396
- workspacePath,
405
+ repoRoot,
397
406
  projectPath,
398
407
  projectFrameworks,
399
408
  packageIds,
@@ -8,7 +8,7 @@ namespace NuGetUpdater.Core.Analyze;
8
8
  internal static class DependencyFinder
9
9
  {
10
10
  public static async Task<ImmutableDictionary<NuGetFramework, ImmutableArray<Dependency>>> GetDependenciesAsync(
11
- string workspacePath,
11
+ string repoRoot,
12
12
  string projectPath,
13
13
  IEnumerable<NuGetFramework> frameworks,
14
14
  ImmutableHashSet<string> packageIds,
@@ -26,7 +26,7 @@ internal static class DependencyFinder
26
26
  foreach (var framework in frameworks)
27
27
  {
28
28
  var dependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(
29
- workspacePath,
29
+ repoRoot,
30
30
  projectPath,
31
31
  framework.ToString(),
32
32
  packages,
@@ -52,10 +52,10 @@ public abstract class Requirement
52
52
 
53
53
  public static Requirement Parse(string requirement)
54
54
  {
55
- var specificParts = requirement.Split(',');
55
+ var specificParts = requirement.Split(',').Where(p => !string.IsNullOrWhiteSpace(p)).ToArray();
56
56
  if (specificParts.Length == 1)
57
57
  {
58
- return IndividualRequirement.ParseIndividual(requirement);
58
+ return IndividualRequirement.ParseIndividual(specificParts[0]);
59
59
  }
60
60
 
61
61
  var specificRequirements = specificParts.Select(IndividualRequirement.ParseIndividual).ToArray();
@@ -31,6 +31,28 @@ public partial class DiscoveryWorker
31
31
  }
32
32
 
33
33
  public async Task RunAsync(string repoRootPath, string workspacePath, string outputPath)
34
+ {
35
+ WorkspaceDiscoveryResult result;
36
+ try
37
+ {
38
+ result = await RunAsync(repoRootPath, workspacePath);
39
+ }
40
+ catch (HttpRequestException ex)
41
+ when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
42
+ {
43
+ result = new WorkspaceDiscoveryResult
44
+ {
45
+ ErrorType = ErrorType.AuthenticationFailure,
46
+ ErrorDetails = "(" + string.Join("|", NuGetContext.GetPackageSourceUrls(PathHelper.JoinPath(repoRootPath, workspacePath))) + ")",
47
+ Path = workspacePath,
48
+ Projects = [],
49
+ };
50
+ }
51
+
52
+ await WriteResultsAsync(repoRootPath, outputPath, result);
53
+ }
54
+
55
+ internal async Task<WorkspaceDiscoveryResult> RunAsync(string repoRootPath, string workspacePath)
34
56
  {
35
57
  MSBuildHelper.RegisterMSBuild(Environment.CurrentDirectory, repoRootPath);
36
58
 
@@ -51,62 +73,46 @@ public partial class DiscoveryWorker
51
73
  ImmutableArray<ProjectDiscoveryResult> projectResults = [];
52
74
  WorkspaceDiscoveryResult result;
53
75
 
54
- try
76
+ if (Directory.Exists(workspacePath))
55
77
  {
56
- if (Directory.Exists(workspacePath))
57
- {
58
- _logger.Log($"Discovering build files in workspace [{workspacePath}].");
78
+ _logger.Log($"Discovering build files in workspace [{workspacePath}].");
59
79
 
60
- dotNetToolsJsonDiscovery = DotNetToolsJsonDiscovery.Discover(repoRootPath, workspacePath, _logger);
61
- globalJsonDiscovery = GlobalJsonDiscovery.Discover(repoRootPath, workspacePath, _logger);
80
+ dotNetToolsJsonDiscovery = DotNetToolsJsonDiscovery.Discover(repoRootPath, workspacePath, _logger);
81
+ globalJsonDiscovery = GlobalJsonDiscovery.Discover(repoRootPath, workspacePath, _logger);
62
82
 
63
- if (globalJsonDiscovery is not null)
64
- {
65
- await TryRestoreMSBuildSdksAsync(repoRootPath, workspacePath, globalJsonDiscovery.Dependencies, _logger);
66
- }
83
+ if (globalJsonDiscovery is not null)
84
+ {
85
+ await TryRestoreMSBuildSdksAsync(repoRootPath, workspacePath, globalJsonDiscovery.Dependencies, _logger);
86
+ }
67
87
 
68
- // this next line should throw or something
69
- projectResults = await RunForDirectoryAsnyc(repoRootPath, workspacePath);
88
+ // this next line should throw or something
89
+ projectResults = await RunForDirectoryAsnyc(repoRootPath, workspacePath);
70
90
 
71
- directoryPackagesPropsDiscovery = DirectoryPackagesPropsDiscovery.Discover(repoRootPath, workspacePath, projectResults, _logger);
91
+ directoryPackagesPropsDiscovery = DirectoryPackagesPropsDiscovery.Discover(repoRootPath, workspacePath, projectResults, _logger);
72
92
 
73
- if (directoryPackagesPropsDiscovery is not null)
74
- {
75
- projectResults = projectResults.Remove(projectResults.First(p => p.FilePath.Equals(directoryPackagesPropsDiscovery.FilePath, StringComparison.OrdinalIgnoreCase)));
76
- }
77
- }
78
- else
93
+ if (directoryPackagesPropsDiscovery is not null)
79
94
  {
80
- _logger.Log($"Workspace path [{workspacePath}] does not exist.");
95
+ projectResults = projectResults.Remove(projectResults.First(p => p.FilePath.Equals(directoryPackagesPropsDiscovery.FilePath, StringComparison.OrdinalIgnoreCase)));
81
96
  }
82
-
83
- result = new WorkspaceDiscoveryResult
84
- {
85
- Path = initialWorkspacePath,
86
- DotNetToolsJson = dotNetToolsJsonDiscovery,
87
- GlobalJson = globalJsonDiscovery,
88
- DirectoryPackagesProps = directoryPackagesPropsDiscovery,
89
- Projects = projectResults.OrderBy(p => p.FilePath).ToImmutableArray(),
90
- };
91
97
  }
92
- catch (HttpRequestException ex)
93
- when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
98
+ else
94
99
  {
95
- // TODO: consolidate this error handling between AnalyzeWorker, DiscoveryWorker, and UpdateWorker
96
- result = new WorkspaceDiscoveryResult
97
- {
98
- ErrorType = ErrorType.AuthenticationFailure,
99
- ErrorDetails = "(" + string.Join("|", NuGetContext.GetPackageSourceUrls(workspacePath)) + ")",
100
- Path = initialWorkspacePath,
101
- Projects = [],
102
- };
100
+ _logger.Log($"Workspace path [{workspacePath}] does not exist.");
103
101
  }
104
102
 
105
- await WriteResultsAsync(repoRootPath, outputPath, result);
103
+ result = new WorkspaceDiscoveryResult
104
+ {
105
+ Path = initialWorkspacePath,
106
+ DotNetToolsJson = dotNetToolsJsonDiscovery,
107
+ GlobalJson = globalJsonDiscovery,
108
+ DirectoryPackagesProps = directoryPackagesPropsDiscovery,
109
+ Projects = projectResults.OrderBy(p => p.FilePath).ToImmutableArray(),
110
+ };
106
111
 
107
112
  _logger.Log("Discovery complete.");
108
-
109
113
  _processedProjectPaths.Clear();
114
+
115
+ return result;
110
116
  }
111
117
 
112
118
  /// <summary>
@@ -21,7 +21,8 @@
21
21
  </ItemGroup>
22
22
 
23
23
  <ItemGroup>
24
- <InternalsVisibleTo Include="NuGetUpdater.Core.Test"/>
24
+ <InternalsVisibleTo Include="NuGetUpdater.Cli.Test" />
25
+ <InternalsVisibleTo Include="NuGetUpdater.Core.Test" />
25
26
  </ItemGroup>
26
27
 
27
28
  </Project>
@@ -0,0 +1,6 @@
1
+ namespace NuGetUpdater.Core.Run.ApiModel;
2
+
3
+ public sealed record AllowedUpdate
4
+ {
5
+ public string UpdateType { get; init; } = "all";
6
+ }