dependabot-nuget 0.287.0 → 0.289.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.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/.gitignore +1 -0
  3. data/helpers/lib/NuGetUpdater/Directory.Build.targets +17 -0
  4. data/helpers/lib/NuGetUpdater/Directory.Packages.props +26 -17
  5. data/helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Packaging/NuGet.Packaging.csproj +0 -1
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +7 -3
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +1 -1
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +3 -1
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +88 -47
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +31 -16
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +1 -1
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementArrayConverter.cs +39 -0
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +1 -1
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Clone/ShellGitCommandHandler.cs +1 -1
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.props +7 -0
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.targets +10 -0
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +64 -53
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DotNetToolsJsonDiscovery.cs +2 -2
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/GlobalJsonDiscovery.cs +2 -2
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +17 -5
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscoveryResult.cs +3 -1
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +3 -0
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +429 -12
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +0 -1
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +12 -2
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/JsonBuildFile.cs +1 -1
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/CompatabilityChecker.cs +2 -2
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +7 -2
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Job.cs +23 -0
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +43 -58
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/TargetFrameworkReporter.targets +13 -0
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +13 -43
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/DotNetToolsJsonUpdater.cs +4 -4
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/GlobalJsonUpdater.cs +5 -5
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +3 -10
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +40 -33
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +12 -11
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +16 -12
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/CollectionExtensions.cs +17 -0
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ConsoleLogger.cs +1 -1
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DependencyConflictResolver.cs +19 -19
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ILogger.cs +11 -1
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +74 -20
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -17
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathComparer.cs +31 -0
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +46 -10
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProjectHelper.cs +96 -0
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +135 -3
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +71 -38
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +66 -4
  51. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Proj.cs +11 -5
  52. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +808 -222
  53. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +477 -97
  54. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +5 -9
  55. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +494 -0
  56. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +46 -1
  57. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/NuGetUpdater.Core.Test.csproj +0 -1
  58. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +401 -77
  59. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +35 -2
  60. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatedDependencyListTests.cs +60 -2
  61. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryDirectory.cs +3 -2
  62. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestLogger.cs +1 -1
  63. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/BindingRedirectsTests.cs +1 -1
  64. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +8 -4
  65. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +40 -0
  66. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +1 -1
  67. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/AssertEx.cs +1 -1
  68. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/LinuxOnlyAttribute.cs +12 -0
  69. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +8 -5
  70. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/PathHelperTests.cs +49 -3
  71. data/lib/dependabot/nuget/analysis/analysis_json_reader.rb +3 -1
  72. data/lib/dependabot/nuget/file_fetcher.rb +12 -393
  73. data/lib/dependabot/nuget/file_parser.rb +23 -54
  74. data/lib/dependabot/nuget/file_updater.rb +21 -16
  75. data/lib/dependabot/nuget/native_discovery/native_dependency_file_discovery.rb +2 -9
  76. data/lib/dependabot/nuget/native_discovery/native_discovery_json_reader.rb +183 -80
  77. data/lib/dependabot/nuget/native_discovery/native_project_discovery.rb +25 -3
  78. data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +1 -11
  79. data/lib/dependabot/nuget/native_helpers.rb +13 -4
  80. data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +17 -4
  81. metadata +15 -12
  82. data/helpers/lib/NuGetUpdater/NuGetProjects/Directory.Packages.props +0 -29
  83. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementConverter.cs +0 -17
  84. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscovery.cs +0 -69
  85. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscoveryResult.cs +0 -11
  86. data/lib/dependabot/nuget/file_fetcher/import_paths_finder.rb +0 -73
  87. data/lib/dependabot/nuget/file_fetcher/sln_project_paths_finder.rb +0 -60
  88. data/lib/dependabot/nuget/native_discovery/native_directory_packages_props_discovery.rb +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bb2d903f08322511a7917fba47df7b66208dbbaca42e52d30a1954f9ef3eaa2
4
- data.tar.gz: f19cfed3ad2939c93812727546b53ecec603c712641a6c1d0581469cce72d584
3
+ metadata.gz: 36551f131fff2d82f525e8eb3bd17f26da2d435f4c44484f2b91e0253f041e8f
4
+ data.tar.gz: c97b1b5899bfac76abd674bf58f8853b7790b5e90d74089f2f663dd12f82fd89
5
5
  SHA512:
6
- metadata.gz: a3fdc15bd985678106cf45f57c6af6dd4be57858f54b50abea6f4521a8aed3ab66b7ca67cb54f9e73dabe536d8c012619bbf049662207211bc92cbb5e938c321
7
- data.tar.gz: 3542f489f10b67fe78b3bd55703cc420a58279bf5fb131da4a99be0d99a20fcd7430b124c4b49100929b74f39178b3c7e108e7bb0170baef5f5a91a16dfbd63f
6
+ metadata.gz: '09e24d02174892b6d10f70bd7e26a200ff0f5d352ba3a69d826598a891d52990c3fd1e839088e4d797df0af6edb53fdb9f3ef9205352c2641cc818b3d603fb97'
7
+ data.tar.gz: 3d9b2b81fee8ff8791796f9d7453f82cdd72a79d2ba3a103303475378fd387d9fb6caedb57688b322dffdb019172ca03910ae6256f79c392d99a233f110e585e
@@ -4,3 +4,4 @@ bin/
4
4
  obj/
5
5
  Properties/launchSettings.json
6
6
  NuGetUpdater.sln.DotSettings.user
7
+ *.binlog
@@ -0,0 +1,17 @@
1
+ <Project>
2
+ <ItemGroup>
3
+ <!--
4
+ The NuGetUpdater.Core project needs to reference `Microsoft.Build.*`, et al. packages, but they require some
5
+ special handling. The documentation explains that:
6
+
7
+ https://learn.microsoft.com/en-us/visualstudio/msbuild/find-and-use-msbuild-versions?view=vs-2022#use-nuget-packages-preferred
8
+
9
+ The `ExcludeAssets` attribute doesn't do what we'd like through a <ProjectReference> element, so to get around that
10
+ we're adding the packages to _all_ projects so they all get the `ExcludeAssets` behavior. For more information see
11
+ this: https://github.com/dotnet/sdk/issues/42708
12
+ -->
13
+ <PackageReference Include="Microsoft.Build" ExcludeAssets="runtime" PrivateAssets="all" />
14
+ <PackageReference Include="Microsoft.Build.Framework" ExcludeAssets="runtime" PrivateAssets="all" />
15
+ <PackageReference Include="Microsoft.Build.Utilities.Core" ExcludeAssets="runtime" PrivateAssets="all" />
16
+ </ItemGroup>
17
+ </Project>
@@ -4,30 +4,39 @@
4
4
  <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
5
5
  </PropertyGroup>
6
6
 
7
- <ItemGroup>
8
- <PackageVersion Include="DiffPlex" Version="1.7.1" />
7
+ <PropertyGroup>
8
+ <MSBuildPackageVersion>17.12.6</MSBuildPackageVersion>
9
+ </PropertyGroup>
9
10
 
11
+ <ItemGroup>
12
+ <PackageVersion Include="DiffPlex" Version="1.7.2" />
10
13
  <PackageVersion Include="GuiLabs.Language.Xml" Version="1.2.93" />
11
-
12
- <PackageVersion Include="Microsoft.Build.Locator" Version="1.6.1" />
13
- <PackageVersion Include="Microsoft.Build" Version="17.5.0" ExcludeAssets="Runtime" PrivateAssets="All" />
14
- <PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.5.0" ExcludeAssets="Runtime" PrivateAssets="All" />
15
-
16
- <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
17
-
18
- <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
19
-
20
- <PackageVersion Include="NuGet.Core" Version="2.14.0-rtm-832" Aliases="CoreV2" />
21
-
14
+ <PackageVersion Include="Microsoft.Build.Locator" Version="1.7.8" />
15
+ <PackageVersion Include="Microsoft.Build" Version="$(MSBuildPackageVersion)" />
16
+ <PackageVersion Include="Microsoft.Build.Framework" Version="$(MSBuildPackageVersion)" />
17
+ <PackageVersion Include="Microsoft.Build.Tasks.Core" Version="$(MSBuildPackageVersion)" />
18
+ <PackageVersion Include="Microsoft.Build.Utilities.Core" Version="$(MSBuildPackageVersion)" />
19
+ <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" />
20
+ <PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
21
+ <PackageVersion Include="Microsoft.Extensions.FileProviders.Abstractions" Version="9.0.0" />
22
+ <PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="9.0.0" />
23
+ <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
24
+ <PackageVersion Include="Microsoft.VisualStudio.Setup.Configuration.Interop" Version="3.12.2149" />
25
+ <PackageVersion Include="Microsoft.Web.Xdt" Version="3.1.0" />
26
+ <PackageVersion Include="MSBuild.StructuredLogger" Version="2.2.386" />
27
+ <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
28
+ <PackageVersion Include="NuGet.Core" Version="2.14.0" Aliases="CoreV2" />
22
29
  <PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
30
+ <PackageVersion Include="System.ComponentModel.Composition" Version="9.0.0" />
23
31
  <PackageVersion Include="System.Net.Http" Version="4.3.4" />
24
32
  <PackageVersion Include="System.Formats.Asn1" Version="8.0.1" />
25
- <PackageVersion Include="System.Security.Cryptography.Pkcs" Version="8.0.0" />
33
+ <PackageVersion Include="System.Security.Cryptography.Pkcs" Version="9.0.0" />
34
+ <PackageVersion Include="System.Security.Cryptography.ProtectedData" Version="9.0.0" />
26
35
  <PackageVersion Include="System.Text.Json" Version="8.0.4" />
27
36
  <PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
28
-
29
- <PackageVersion Include="xunit" Version="2.4.2" />
30
- <PackageVersion Include="xunit.runner.visualstudio" Version="2.4.5" />
37
+ <PackageVersion Include="System.Threading.Tasks.Dataflow" Version="9.0.0" />
38
+ <PackageVersion Include="xunit" Version="2.9.2" />
39
+ <PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
31
40
  </ItemGroup>
32
41
 
33
42
  </Project>
@@ -14,7 +14,6 @@
14
14
  <ItemGroup>
15
15
  <PackageReference Include="Newtonsoft.Json" />
16
16
  <PackageReference Include="System.Security.Cryptography.Pkcs" />
17
- <PackageReference Include="System.Security.Cryptography.Cng" />
18
17
  </ItemGroup>
19
18
 
20
19
  <ItemGroup>
@@ -7,6 +7,7 @@ namespace NuGetUpdater.Cli.Commands;
7
7
 
8
8
  internal static class DiscoverCommand
9
9
  {
10
+ internal static readonly Option<FileInfo> JobPathOption = new("--job-path") { IsRequired = true };
10
11
  internal static readonly Option<DirectoryInfo> RepoRootOption = new("--repo-root") { IsRequired = true };
11
12
  internal static readonly Option<string> WorkspaceOption = new("--workspace") { IsRequired = true };
12
13
  internal static readonly Option<FileInfo> OutputOption = new("--output") { IsRequired = true };
@@ -15,6 +16,7 @@ internal static class DiscoverCommand
15
16
  {
16
17
  Command command = new("discover", "Generates a report of the workspace dependencies and where they are located.")
17
18
  {
19
+ JobPathOption,
18
20
  RepoRootOption,
19
21
  WorkspaceOption,
20
22
  OutputOption
@@ -22,11 +24,13 @@ internal static class DiscoverCommand
22
24
 
23
25
  command.TreatUnmatchedTokensAsErrors = true;
24
26
 
25
- command.SetHandler(async (repoRoot, workspace, outputPath) =>
27
+ command.SetHandler(async (jobPath, repoRoot, workspace, outputPath) =>
26
28
  {
27
- var worker = new DiscoveryWorker(new ConsoleLogger());
29
+ var logger = new ConsoleLogger();
30
+ var experimentsManager = await ExperimentsManager.FromJobFileAsync(jobPath.FullName, logger);
31
+ var worker = new DiscoveryWorker(experimentsManager, logger);
28
32
  await worker.RunAsync(repoRoot.FullName, workspace, outputPath.FullName);
29
- }, RepoRootOption, WorkspaceOption, OutputOption);
33
+ }, JobPathOption, RepoRootOption, WorkspaceOption, OutputOption);
30
34
 
31
35
  return command;
32
36
  }
@@ -35,7 +35,7 @@ internal static class RunCommand
35
35
  var apiHandler = new HttpApiHandler(apiUrl.ToString(), jobId);
36
36
  var logger = new ConsoleLogger();
37
37
  var experimentsManager = await ExperimentsManager.FromJobFileAsync(jobPath.FullName, logger);
38
- var discoverWorker = new DiscoveryWorker(logger);
38
+ var discoverWorker = new DiscoveryWorker(experimentsManager, logger);
39
39
  var analyzeWorker = new AnalyzeWorker(logger);
40
40
  var updateWorker = new UpdaterWorker(experimentsManager, logger);
41
41
  var worker = new RunWorker(apiHandler, discoverWorker, analyzeWorker, updateWorker, logger);
@@ -94,7 +94,9 @@ public partial class EntryPointTests
94
94
  "TargetFrameworks": [
95
95
  "net8.0"
96
96
  ],
97
- "ReferencedProjectPaths": []
97
+ "ReferencedProjectPaths": [],
98
+ "ImportedFiles": [],
99
+ "AdditionalFiles": []
98
100
  }
99
101
  ],
100
102
  "DirectoryPackagesProps": null,
@@ -17,12 +17,16 @@ public partial class EntryPointTests
17
17
  {
18
18
  public class Discover : DiscoveryWorkerTestBase
19
19
  {
20
- [Fact]
21
- public async Task PathWithSpaces()
20
+ [Theory]
21
+ [InlineData(true)]
22
+ [InlineData(false)]
23
+ public async Task PathWithSpaces(bool useDirectDiscovery)
22
24
  {
23
25
  await RunAsync(path =>
24
26
  [
25
27
  "discover",
28
+ "--job-path",
29
+ Path.Combine(path, "job.json"),
26
30
  "--repo-root",
27
31
  path,
28
32
  "--workspace",
@@ -30,11 +34,15 @@ public partial class EntryPointTests
30
34
  "--output",
31
35
  Path.Combine(path, DiscoveryWorker.DiscoveryResultFileName),
32
36
  ],
33
- packages: [],
37
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = useDirectDiscovery },
38
+ packages:
39
+ [
40
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.2.3", "net8.0"),
41
+ ],
34
42
  initialFiles:
35
43
  [
36
44
  ("path/to/some directory with spaces/project.csproj", """
37
- <Project Sdk="Microsoft.NETSdk">
45
+ <Project Sdk="Microsoft.NET.Sdk">
38
46
  <PropertyGroup>
39
47
  <TargetFramework>net8.0</TargetFramework>
40
48
  </PropertyGroup>
@@ -52,26 +60,31 @@ public partial class EntryPointTests
52
60
  {
53
61
  FilePath = "project.csproj",
54
62
  TargetFrameworks = ["net8.0"],
55
- ReferencedProjectPaths = [],
56
- ExpectedDependencyCount = 2,
57
63
  Dependencies = [
58
64
  new("Some.Package", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
59
65
  ],
60
66
  Properties = [
61
67
  new("TargetFramework", "net8.0", "path/to/some directory with spaces/project.csproj"),
62
68
  ],
69
+ ReferencedProjectPaths = [],
70
+ ImportedFiles = [],
71
+ AdditionalFiles = [],
63
72
  }
64
73
  ]
65
74
  }
66
75
  );
67
76
  }
68
77
 
69
- [Fact]
70
- public async Task WithSolution()
78
+ [Theory]
79
+ [InlineData(true)]
80
+ [InlineData(false)]
81
+ public async Task WithSolution(bool useDirectDiscovery)
71
82
  {
72
83
  await RunAsync(path =>
73
84
  [
74
85
  "discover",
86
+ "--job-path",
87
+ Path.Combine(path, "job.json"),
75
88
  "--repo-root",
76
89
  path,
77
90
  "--workspace",
@@ -79,6 +92,7 @@ public partial class EntryPointTests
79
92
  "--output",
80
93
  Path.Combine(path, DiscoveryWorker.DiscoveryResultFileName),
81
94
  ],
95
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = useDirectDiscovery },
82
96
  packages:
83
97
  [
84
98
  MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"),
@@ -141,13 +155,14 @@ public partial class EntryPointTests
141
155
  {
142
156
  FilePath = "path/to/my.csproj",
143
157
  TargetFrameworks = ["net45"],
144
- ReferencedProjectPaths = [],
145
- ExpectedDependencyCount = 2,
146
158
  Dependencies = [
147
159
  new("Some.Package", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"]),
148
160
  ],
149
- Properties = [
150
- new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"),
161
+ Properties = [],
162
+ ReferencedProjectPaths = [],
163
+ ImportedFiles = [],
164
+ AdditionalFiles = [
165
+ "packages.config"
151
166
  ],
152
167
  }
153
168
  ]
@@ -155,12 +170,16 @@ public partial class EntryPointTests
155
170
  );
156
171
  }
157
172
 
158
- [Fact]
159
- public async Task WithProject()
173
+ [Theory]
174
+ [InlineData(true)]
175
+ [InlineData(false)]
176
+ public async Task WithProject(bool useDirectDiscovery)
160
177
  {
161
178
  await RunAsync(path =>
162
179
  [
163
180
  "discover",
181
+ "--job-path",
182
+ Path.Combine(path, "job.json"),
164
183
  "--repo-root",
165
184
  path,
166
185
  "--workspace",
@@ -168,6 +187,7 @@ public partial class EntryPointTests
168
187
  "--output",
169
188
  Path.Combine(path, DiscoveryWorker.DiscoveryResultFileName),
170
189
  ],
190
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = useDirectDiscovery },
171
191
  packages:
172
192
  [
173
193
  MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"),
@@ -207,13 +227,14 @@ public partial class EntryPointTests
207
227
  {
208
228
  FilePath = "my.csproj",
209
229
  TargetFrameworks = ["net45"],
210
- ReferencedProjectPaths = [],
211
- ExpectedDependencyCount = 2,
212
230
  Dependencies = [
213
231
  new("Some.Package", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"])
214
232
  ],
215
- Properties = [
216
- new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"),
233
+ Properties = [],
234
+ ReferencedProjectPaths = [],
235
+ ImportedFiles = [],
236
+ AdditionalFiles = [
237
+ "packages.config"
217
238
  ],
218
239
  }
219
240
  ]
@@ -221,13 +242,17 @@ public partial class EntryPointTests
221
242
  );
222
243
  }
223
244
 
224
- [Fact]
225
- public async Task WithDirectory()
245
+ [Theory]
246
+ [InlineData(true)]
247
+ [InlineData(false)]
248
+ public async Task WithDirectory(bool useDirectDiscovery)
226
249
  {
227
250
  var workspacePath = "path/to/";
228
251
  await RunAsync(path =>
229
252
  [
230
253
  "discover",
254
+ "--job-path",
255
+ Path.Combine(path, "job.json"),
231
256
  "--repo-root",
232
257
  path,
233
258
  "--workspace",
@@ -235,6 +260,7 @@ public partial class EntryPointTests
235
260
  "--output",
236
261
  Path.Combine(path, DiscoveryWorker.DiscoveryResultFileName),
237
262
  ],
263
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = useDirectDiscovery },
238
264
  packages:
239
265
  [
240
266
  MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"),
@@ -274,13 +300,14 @@ public partial class EntryPointTests
274
300
  {
275
301
  FilePath = "my.csproj",
276
302
  TargetFrameworks = ["net45"],
277
- ReferencedProjectPaths = [],
278
- ExpectedDependencyCount = 2,
279
303
  Dependencies = [
280
304
  new("Some.Package", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"])
281
305
  ],
282
- Properties = [
283
- new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"),
306
+ Properties = [],
307
+ ReferencedProjectPaths = [],
308
+ ImportedFiles = [],
309
+ AdditionalFiles = [
310
+ "packages.config"
284
311
  ],
285
312
  }
286
313
  ]
@@ -294,6 +321,8 @@ public partial class EntryPointTests
294
321
  await RunAsync(path =>
295
322
  [
296
323
  "discover",
324
+ "--job-path",
325
+ Path.Combine(path, "job.json"),
297
326
  "--repo-root",
298
327
  path,
299
328
  "--workspace",
@@ -304,27 +333,33 @@ public partial class EntryPointTests
304
333
  new[]
305
334
  {
306
335
  ("path/to/my.csproj", """
307
- <Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
336
+ <Project Sdk="Microsoft.NET.Sdk">
308
337
  <PropertyGroup>
309
338
  <TargetFramework>net8.0</TargetFramework>
339
+ <ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
310
340
  </PropertyGroup>
311
341
  <ItemGroup>
312
- <PackageReference Include="Newtonsoft.Json" Version="7.0.1" />
342
+ <PackageReference Include="Package.A" Version="1.2.3" />
313
343
  </ItemGroup>
314
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
315
344
  </Project>
316
345
  """),
317
346
  ("path/Directory.Build.props", """
318
347
  <Project>
319
- <ItemGroup Condition="'$(ManagePackageVersionsCentrally)' == 'true'">
320
- <GlobalPackageReference Include="System.Text.Json" Version="8.0.3" />
321
- </ItemGroup>
322
348
  <ItemGroup Condition="'$(ManagePackageVersionsCentrally)' != 'true'">
323
- <PackageReference Include="System.Text.Json" Version="8.0.3" />
349
+ <PackageReference Include="Package.B" Version="4.5.6" />
350
+ </ItemGroup>
351
+ <ItemGroup Condition="'$(ManagePackageVersionsCentrally)' == 'true'">
352
+ <GlobalPackageReference Include="Package.B" Version="7.8.9" />
324
353
  </ItemGroup>
325
354
  </Project>
326
355
  """)
327
356
  },
357
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = true },
358
+ packages:
359
+ [
360
+ MockNuGetPackage.CreateSimplePackage("Package.A", "1.2.3", "net8.0"),
361
+ MockNuGetPackage.CreateSimplePackage("Package.B", "4.5.6", "net8.0"),
362
+ ],
328
363
  expectedResult: new()
329
364
  {
330
365
  Path = "path/to",
@@ -333,29 +368,22 @@ public partial class EntryPointTests
333
368
  {
334
369
  FilePath = "my.csproj",
335
370
  TargetFrameworks = ["net8.0"],
336
- ReferencedProjectPaths = [],
337
371
  ExpectedDependencyCount = 2,
338
372
  Dependencies = [
339
- new("Newtonsoft.Json", "7.0.1", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
340
- // $(ManagePackageVersionsCentrally) evaluates false by default, we only get a PackageReference
341
- new("System.Text.Json", "8.0.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0"])
373
+ new("Package.A", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
374
+ new("Package.B", "4.5.6", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
342
375
  ],
343
376
  Properties = [
377
+ new("ManagePackageVersionsCentrally", "false", "path/to/my.csproj"),
344
378
  new("TargetFramework", "net8.0", "path/to/my.csproj"),
345
379
  ],
346
- },
347
- new()
348
- {
349
- FilePath = "../Directory.Build.props",
350
380
  ReferencedProjectPaths = [],
351
- ExpectedDependencyCount = 2,
352
- Dependencies = [
353
- new("System.Text.Json", "8.0.3", DependencyType.PackageReference, IsDirect: true),
354
- new("System.Text.Json", "8.0.3", DependencyType.GlobalPackageReference, IsDirect: true)
381
+ ImportedFiles = [
382
+ "../Directory.Build.props"
355
383
  ],
356
- Properties = [],
384
+ AdditionalFiles = [],
357
385
  }
358
- ]
386
+ ],
359
387
  }
360
388
  );
361
389
  }
@@ -364,8 +392,10 @@ public partial class EntryPointTests
364
392
  Func<string, string[]> getArgs,
365
393
  TestFile[] initialFiles,
366
394
  ExpectedWorkspaceDiscoveryResult expectedResult,
367
- MockNuGetPackage[]? packages = null)
395
+ MockNuGetPackage[]? packages = null,
396
+ ExperimentsManager? experimentsManager = null)
368
397
  {
398
+ experimentsManager ??= new ExperimentsManager();
369
399
  var actualResult = await RunDiscoveryAsync(initialFiles, async path =>
370
400
  {
371
401
  var sb = new StringBuilder();
@@ -378,8 +408,19 @@ public partial class EntryPointTests
378
408
 
379
409
  try
380
410
  {
411
+ await UpdateWorkerTestBase.MockJobFileInDirectory(path, experimentsManager);
381
412
  await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(packages, path);
382
413
  var args = getArgs(path);
414
+
415
+ // manually pull out the experiments manager for the validate step below
416
+ for (int i = 0; i < args.Length - 1; i++)
417
+ {
418
+ if (args[i] == "--job-path")
419
+ {
420
+ experimentsManager = await ExperimentsManager.FromJobFileAsync(args[i + 1], new TestLogger());
421
+ }
422
+ }
423
+
383
424
  var result = await Program.Main(args);
384
425
  if (result != 0)
385
426
  {
@@ -398,7 +439,7 @@ public partial class EntryPointTests
398
439
  return resultObject!;
399
440
  });
400
441
 
401
- ValidateWorkspaceResult(expectedResult, actualResult);
442
+ ValidateWorkspaceResult(expectedResult, actualResult, experimentsManager);
402
443
  }
403
444
  }
404
445
  }
@@ -21,7 +21,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
21
21
  internal static readonly JsonSerializerOptions SerializerOptions = new()
22
22
  {
23
23
  WriteIndented = true,
24
- Converters = { new JsonStringEnumConverter(), new RequirementConverter() },
24
+ Converters = { new JsonStringEnumConverter(), new RequirementArrayConverter() },
25
25
  };
26
26
 
27
27
  public AnalyzeWorker(ILogger logger)
@@ -32,15 +32,15 @@ public partial class AnalyzeWorker : IAnalyzeWorker
32
32
  public async Task RunAsync(string repoRoot, string discoveryPath, string dependencyPath, string analysisDirectory)
33
33
  {
34
34
  var analysisResult = await RunWithErrorHandlingAsync(repoRoot, discoveryPath, dependencyPath);
35
- var dependencyInfo = await DeserializeJsonFileAsync<DependencyInfo>(dependencyPath, nameof(DependencyInfo));
35
+ var dependencyInfo = await DeserializeDependencyInfoFileAsync(dependencyPath);
36
36
  await WriteResultsAsync(analysisDirectory, dependencyInfo.Name, analysisResult, _logger);
37
37
  }
38
38
 
39
39
  internal async Task<AnalysisResult> RunWithErrorHandlingAsync(string repoRoot, string discoveryPath, string dependencyPath)
40
40
  {
41
41
  AnalysisResult analysisResult;
42
- var discovery = await DeserializeJsonFileAsync<WorkspaceDiscoveryResult>(discoveryPath, nameof(WorkspaceDiscoveryResult));
43
- var dependencyInfo = await DeserializeJsonFileAsync<DependencyInfo>(dependencyPath, nameof(DependencyInfo));
42
+ var discovery = await DeserializeWorkspaceDiscoveryResultFileAsync(discoveryPath);
43
+ var dependencyInfo = await DeserializeDependencyInfoFileAsync(dependencyPath);
44
44
 
45
45
  try
46
46
  {
@@ -68,7 +68,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
68
68
  {
69
69
  var startingDirectory = PathHelper.JoinPath(repoRoot, discovery.Path);
70
70
 
71
- _logger.Log($"Starting analysis of {dependencyInfo.Name}...");
71
+ _logger.Info($"Starting analysis of {dependencyInfo.Name}...");
72
72
 
73
73
  // We need to find all projects which have the given dependency. Even in cases that they
74
74
  // have it transitively may require that peer dependencies be updated in the project.
@@ -97,7 +97,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
97
97
  AnalysisResult analysisResult;
98
98
  if (isUpdateNecessary)
99
99
  {
100
- _logger.Log($" Determining multi-dependency property.");
100
+ _logger.Info($" Determining multi-dependency property.");
101
101
  var multiDependencies = DetermineMultiDependencyDetails(
102
102
  discovery,
103
103
  dependencyInfo.Name,
@@ -117,7 +117,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
117
117
  .ToImmutableArray()
118
118
  : projectFrameworks;
119
119
 
120
- _logger.Log($" Finding updated version.");
120
+ _logger.Info($" Finding updated version.");
121
121
  updatedVersion = await FindUpdatedVersionAsync(
122
122
  startingDirectory,
123
123
  dependencyInfo,
@@ -127,7 +127,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
127
127
  _logger,
128
128
  CancellationToken.None);
129
129
 
130
- _logger.Log($" Finding updated peer dependencies.");
130
+ _logger.Info($" Finding updated peer dependencies.");
131
131
  if (updatedVersion is null)
132
132
  {
133
133
  updatedDependencies = [];
@@ -173,7 +173,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
173
173
  UpdatedDependencies = updatedDependencies,
174
174
  };
175
175
 
176
- _logger.Log($"Analysis complete.");
176
+ _logger.Info($"Analysis complete.");
177
177
  return analysisResult;
178
178
  }
179
179
 
@@ -197,13 +197,28 @@ public partial class AnalyzeWorker : IAnalyzeWorker
197
197
  !d.IsTransitive));
198
198
  }
199
199
 
200
- internal static async Task<T> DeserializeJsonFileAsync<T>(string path, string fileType)
200
+ private static Task<WorkspaceDiscoveryResult> DeserializeWorkspaceDiscoveryResultFileAsync(string path)
201
201
  {
202
- var json = File.Exists(path)
203
- ? await File.ReadAllTextAsync(path)
204
- : throw new FileNotFoundException($"{fileType} file not found.", path);
202
+ return DeserializeJsonFileAsync(path, nameof(WorkspaceDiscoveryResult), json => JsonSerializer.Deserialize<WorkspaceDiscoveryResult>(json, SerializerOptions));
203
+ }
204
+
205
+ private static Task<DependencyInfo> DeserializeDependencyInfoFileAsync(string path)
206
+ {
207
+ return DeserializeJsonFileAsync(path, nameof(DependencyInfo), DeserializeDependencyInfo);
208
+ }
205
209
 
206
- return JsonSerializer.Deserialize<T>(json, SerializerOptions)
210
+ internal static DependencyInfo? DeserializeDependencyInfo(string content)
211
+ {
212
+ return JsonSerializer.Deserialize<DependencyInfo>(content, SerializerOptions);
213
+ }
214
+
215
+ private static async Task<T> DeserializeJsonFileAsync<T>(string filePath, string fileType, Func<string, T?> deserializer)
216
+ {
217
+ var json = File.Exists(filePath)
218
+ ? await File.ReadAllTextAsync(filePath)
219
+ : throw new FileNotFoundException($"{fileType} file not found.", filePath);
220
+
221
+ return deserializer(json)
207
222
  ?? throw new InvalidOperationException($"{fileType} file is empty.");
208
223
  }
209
224
 
@@ -391,8 +406,8 @@ public partial class AnalyzeWorker : IAnalyzeWorker
391
406
 
392
407
  var projectFrameworks = projectsWithDependency
393
408
  .SelectMany(p => p.TargetFrameworks)
394
- .Distinct()
395
409
  .Select(NuGetFramework.Parse)
410
+ .Distinct()
396
411
  .ToImmutableArray();
397
412
 
398
413
  // When updating peer dependencies, we only need to consider top-level dependencies.
@@ -468,7 +483,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
468
483
 
469
484
  var resultPath = Path.Combine(analysisDirectory, $"{dependencyName}.json");
470
485
 
471
- logger.Log($" Writing analysis result to [{resultPath}].");
486
+ logger.Info($" Writing analysis result to [{resultPath}].");
472
487
 
473
488
  var resultJson = JsonSerializer.Serialize(result, SerializerOptions);
474
489
  await File.WriteAllTextAsync(path: resultPath, resultJson);
@@ -68,7 +68,7 @@ internal static class CompatibilityChecker
68
68
  var incompatibleFrameworks = projectFrameworks.Where(f => !compatibleFrameworks.Contains(f)).ToArray();
69
69
  if (incompatibleFrameworks.Length > 0)
70
70
  {
71
- logger.Log($"The package {package} is not compatible. Incompatible project frameworks: {string.Join(", ", incompatibleFrameworks.Select(f => f.GetShortFolderName()))}");
71
+ logger.Info($"The package {package} is not compatible. Incompatible project frameworks: {string.Join(", ", incompatibleFrameworks.Select(f => f.GetShortFolderName()))}");
72
72
  return false;
73
73
  }
74
74
 
@@ -0,0 +1,39 @@
1
+ using System.Collections.Immutable;
2
+ using System.Text.Json;
3
+ using System.Text.Json.Serialization;
4
+
5
+ namespace NuGetUpdater.Core.Analyze;
6
+
7
+ public class RequirementArrayConverter : JsonConverter<ImmutableArray<Requirement>>
8
+ {
9
+ public override ImmutableArray<Requirement> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
10
+ {
11
+ var requirements = new List<Requirement>();
12
+ var requirementStrings = JsonSerializer.Deserialize<string[]>(ref reader, options) ?? [];
13
+ foreach (var requirementString in requirementStrings)
14
+ {
15
+ try
16
+ {
17
+ var requirement = Requirement.Parse(requirementString);
18
+ requirements.Add(requirement);
19
+ }
20
+ catch (ArgumentException)
21
+ {
22
+ // couldn't parse, nothing to do
23
+ }
24
+ }
25
+
26
+ return requirements.ToImmutableArray();
27
+ }
28
+
29
+ public override void Write(Utf8JsonWriter writer, ImmutableArray<Requirement> value, JsonSerializerOptions options)
30
+ {
31
+ writer.WriteStartArray();
32
+ foreach (var requirement in value)
33
+ {
34
+ writer.WriteStringValue(requirement.ToString());
35
+ }
36
+
37
+ writer.WriteEndArray();
38
+ }
39
+ }