dependabot-nuget 0.251.0 → 0.253.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/Directory.Common.props +1 -0
  3. data/helpers/lib/NuGetUpdater/Directory.Packages.props +26 -0
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +35 -0
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/NuGetUpdater.Cli.csproj +1 -1
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Program.cs +4 -7
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +251 -0
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +27 -9
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/NuGetUpdater.Cli.Test.csproj +3 -3
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Dependency.cs +56 -1
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyType.cs +1 -1
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscovery.cs +69 -0
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscoveryResult.cs +11 -0
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +217 -0
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DotNetToolsJsonDiscovery.cs +30 -0
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DotNetToolsJsonDiscoveryResult.cs +10 -0
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/GlobalJsonDiscovery.cs +30 -0
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/GlobalJsonDiscoveryResult.cs +10 -0
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/IDiscoveryResult.cs +14 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +29 -0
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscoveryResult.cs +10 -0
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +13 -0
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +128 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +13 -0
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/EvaluationResult.cs +8 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/EvaluationResultType.cs +9 -0
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/BuildFile.cs +6 -8
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/DotNetToolsJsonBuildFile.cs +4 -7
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/GlobalJsonBuildFile.cs +24 -17
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/JsonBuildFile.cs +2 -2
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/PackagesConfigBuildFile.cs +8 -13
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/ProjectBuildFile.cs +100 -19
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/XmlBuildFile.cs +2 -2
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +6 -6
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Property.cs +6 -0
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/DotNetToolsJsonUpdater.cs +23 -36
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/GlobalJsonUpdater.cs +5 -10
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +59 -26
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +5 -20
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/HashSetExtensions.cs +14 -0
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ImmutableArrayExtensions.cs +18 -0
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/JsonHelper.cs +0 -1
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +281 -140
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +27 -4
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +18 -13
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +135 -0
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs +91 -0
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs +71 -0
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +67 -0
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +405 -0
  51. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +306 -0
  52. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +36 -0
  53. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/DotNetToolsJsonBuildFileTests.cs +1 -2
  54. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/GlobalJsonBuildFileTests.cs +2 -3
  55. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/PackagesConfigBuildFileTests.cs +4 -6
  56. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/ProjectBuildFileTests.cs +6 -5
  57. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/NuGetUpdater.Core.Test.csproj +4 -3
  58. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryDirectory.cs +38 -6
  59. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestBase.cs +10 -0
  60. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackagesConfigUpdaterTests.cs +1 -8
  61. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +13 -41
  62. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs +0 -5
  63. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs +0 -5
  64. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs +0 -5
  65. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +0 -5
  66. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +0 -5
  67. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +30 -23
  68. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/AssertEx.cs +272 -0
  69. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/DiffUtil.cs +266 -0
  70. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +239 -161
  71. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/SdkPackageUpdaterHelperTests.cs +7 -11
  72. data/lib/dependabot/nuget/discovery/dependency_details.rb +95 -0
  73. data/lib/dependabot/nuget/discovery/dependency_file_discovery.rb +126 -0
  74. data/lib/dependabot/nuget/discovery/directory_packages_props_discovery.rb +43 -0
  75. data/lib/dependabot/nuget/discovery/discovery_json_reader.rb +83 -0
  76. data/lib/dependabot/nuget/discovery/evaluation_details.rb +63 -0
  77. data/lib/dependabot/nuget/discovery/project_discovery.rb +71 -0
  78. data/lib/dependabot/nuget/discovery/property_details.rb +43 -0
  79. data/lib/dependabot/nuget/discovery/workspace_discovery.rb +66 -0
  80. data/lib/dependabot/nuget/file_parser.rb +19 -128
  81. data/lib/dependabot/nuget/file_updater.rb +28 -60
  82. data/lib/dependabot/nuget/native_helpers.rb +55 -0
  83. data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +3 -8
  84. data/lib/dependabot/nuget/update_checker/dependency_finder.rb +1 -0
  85. data/lib/dependabot/nuget/update_checker/property_updater.rb +1 -0
  86. data/lib/dependabot/nuget/update_checker/tfm_finder.rb +17 -152
  87. data/lib/dependabot/nuget/update_checker/version_finder.rb +1 -6
  88. data/lib/dependabot/nuget/update_checker.rb +4 -1
  89. metadata +44 -25
  90. data/lib/dependabot/nuget/file_parser/dotnet_tools_json_parser.rb +0 -71
  91. data/lib/dependabot/nuget/file_parser/global_json_parser.rb +0 -68
  92. data/lib/dependabot/nuget/file_parser/packages_config_parser.rb +0 -92
  93. data/lib/dependabot/nuget/file_parser/project_file_parser.rb +0 -620
  94. data/lib/dependabot/nuget/file_parser/property_value_finder.rb +0 -225
  95. data/lib/dependabot/nuget/file_updater/property_value_updater.rb +0 -81
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de6f0b0f318838044e74746451b7c9b006d1c7d02a5f0eb9dd435be71e531324
4
- data.tar.gz: a79152fa48bdead211a0116e40a8e2583fbb780c7a84ae9e11c5a61fed9cd243
3
+ metadata.gz: 272069533f6bea5533fb423db28c745b469884c904e393d9708091398a93f9a3
4
+ data.tar.gz: dd0c3fad1ab56f2bc32e509f89552068cc59b02cd21b1878ef1edcca84af45ba
5
5
  SHA512:
6
- metadata.gz: dbb569b37e215ec868f66117759bacc09d3de783add60b2274f261d81a1b55ef0a4fffa77c172db4183490dc0fc390551377ba7a404ddd8e1bf1a4d836f43986
7
- data.tar.gz: be749544dda69391923d1843c254619cf9f2f9afcc9d5de8a58fc7cf1388352084a2de6f2989d002b9fdd4e5d56c55563cbf6a477a3696757522678ddee73599
6
+ metadata.gz: a66d28929da003117a1a5ef125be1acd2dd91a522f715fa1c263610a63e333e5b60ec3343836a1d19b6516527595b88425aed9f7df7a5c3f254579b1a12ec77c
7
+ data.tar.gz: 4fa773a0ff8f2c5e423fd505d111eaf7f84439f99111b68a87e77700290ae0ae97d52318ec9ddabc4d5c80e953bdaef761da96730c82baa8f5c0e36034798e3b
@@ -10,6 +10,7 @@
10
10
  2. Update tests as needed at `NuGetUpdater\NuGetUpdater.Core.Test\FrameworkChecker\CompatibilityCheckerFacts.cs`
11
11
  -->
12
12
  <CommonTargetFramework>net8.0</CommonTargetFramework>
13
+ <ImplicitUsings>enable</ImplicitUsings>
13
14
  <UseArtifactsOutput>true</UseArtifactsOutput>
14
15
  <ArtifactsPath>$(MSBuildThisFileDirectory)artifacts</ArtifactsPath>
15
16
  </PropertyGroup>
@@ -0,0 +1,26 @@
1
+ <Project>
2
+
3
+ <PropertyGroup>
4
+ <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
5
+ </PropertyGroup>
6
+
7
+ <ItemGroup>
8
+ <PackageVersion Include="DiffPlex" Version="1.7.1" />
9
+
10
+ <PackageVersion Include="GuiLabs.Language.Xml" Version="1.2.60" />
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.NET.Test.Sdk" Version="17.5.0" />
17
+
18
+ <PackageVersion Include="NuGet.Core" Version="2.14.0-rtm-832" Aliases="CoreV2" />
19
+
20
+ <PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
21
+
22
+ <PackageVersion Include="xunit" Version="2.4.2" />
23
+ <PackageVersion Include="xunit.runner.visualstudio" Version="2.4.5" />
24
+ </ItemGroup>
25
+
26
+ </Project>
@@ -0,0 +1,35 @@
1
+ using System.CommandLine;
2
+
3
+ using NuGetUpdater.Core;
4
+ using NuGetUpdater.Core.Discover;
5
+
6
+ namespace NuGetUpdater.Cli.Commands;
7
+
8
+ internal static class DiscoverCommand
9
+ {
10
+ internal static readonly Option<DirectoryInfo> RepoRootOption = new("--repo-root", () => new DirectoryInfo(Environment.CurrentDirectory)) { IsRequired = false };
11
+ internal static readonly Option<FileSystemInfo> WorkspaceOption = new("--workspace") { IsRequired = true };
12
+ internal static readonly Option<string> OutputOption = new("--output", () => DiscoveryWorker.DiscoveryResultFileName) { IsRequired = false };
13
+ internal static readonly Option<bool> VerboseOption = new("--verbose", getDefaultValue: () => false);
14
+
15
+ internal static Command GetCommand(Action<int> setExitCode)
16
+ {
17
+ Command command = new("discover", "Generates a report of the workspace dependencies and where they are located.")
18
+ {
19
+ RepoRootOption,
20
+ WorkspaceOption,
21
+ OutputOption,
22
+ VerboseOption
23
+ };
24
+
25
+ command.TreatUnmatchedTokensAsErrors = true;
26
+
27
+ command.SetHandler(async (repoRoot, workspace, outputPath, verbose) =>
28
+ {
29
+ var worker = new DiscoveryWorker(new Logger(verbose));
30
+ await worker.RunAsync(repoRoot.FullName, workspace.FullName, outputPath);
31
+ }, RepoRootOption, WorkspaceOption, OutputOption, VerboseOption);
32
+
33
+ return command;
34
+ }
35
+ }
@@ -10,7 +10,7 @@
10
10
  </ItemGroup>
11
11
 
12
12
  <ItemGroup>
13
- <PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
13
+ <PackageReference Include="System.CommandLine" />
14
14
  </ItemGroup>
15
15
 
16
16
  <ItemGroup>
@@ -1,6 +1,4 @@
1
- using System;
2
1
  using System.CommandLine;
3
- using System.Threading.Tasks;
4
2
 
5
3
  using NuGetUpdater.Cli.Commands;
6
4
 
@@ -16,16 +14,15 @@ internal sealed class Program
16
14
  var command = new RootCommand
17
15
  {
18
16
  FrameworkCheckCommand.GetCommand(setExitCode),
17
+ DiscoverCommand.GetCommand(setExitCode),
19
18
  UpdateCommand.GetCommand(setExitCode),
20
19
  };
21
20
  command.TreatUnmatchedTokensAsErrors = true;
22
21
 
23
22
  var result = await command.InvokeAsync(args);
24
- if (result != 0)
25
- {
26
- exitCode = result;
27
- }
28
23
 
29
- return exitCode;
24
+ return result == 0
25
+ ? exitCode
26
+ : result;
30
27
  }
31
28
  }
@@ -0,0 +1,251 @@
1
+ using System.Collections.Immutable;
2
+ using System.Text;
3
+
4
+ using NuGetUpdater.Core;
5
+ using NuGetUpdater.Core.Test.Discover;
6
+
7
+ using Xunit;
8
+
9
+ namespace NuGetUpdater.Cli.Test;
10
+
11
+ using TestFile = (string Path, string Content);
12
+
13
+ public partial class EntryPointTests
14
+ {
15
+ public class Discover : DiscoveryWorkerTestBase
16
+ {
17
+ [Fact]
18
+ public async Task WithSolution()
19
+ {
20
+ string solutionPath = "path/to/solution.sln";
21
+ await RunAsync(path =>
22
+ [
23
+ "discover",
24
+ "--repo-root",
25
+ path,
26
+ "--workspace",
27
+ path,
28
+ ],
29
+ new[]
30
+ {
31
+ (solutionPath, """
32
+ Microsoft Visual Studio Solution File, Format Version 12.00
33
+ # Visual Studio 14
34
+ VisualStudioVersion = 14.0.22705.0
35
+ MinimumVisualStudioVersion = 10.0.40219.1
36
+ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "my", "my.csproj", "{782E0C0A-10D3-444D-9640-263D03D2B20C}"
37
+ EndProject
38
+ Global
39
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
40
+ Debug|Any CPU = Debug|Any CPU
41
+ Release|Any CPU = Release|Any CPU
42
+ EndGlobalSection
43
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
44
+ {782E0C0A-10D3-444D-9640-263D03D2B20C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45
+ {782E0C0A-10D3-444D-9640-263D03D2B20C}.Debug|Any CPU.Build.0 = Debug|Any CPU
46
+ {782E0C0A-10D3-444D-9640-263D03D2B20C}.Release|Any CPU.ActiveCfg = Release|Any CPU
47
+ {782E0C0A-10D3-444D-9640-263D03D2B20C}.Release|Any CPU.Build.0 = Release|Any CPU
48
+ EndGlobalSection
49
+ GlobalSection(SolutionProperties) = preSolution
50
+ HideSolutionNode = FALSE
51
+ EndGlobalSection
52
+ EndGlobal
53
+ """),
54
+ ("path/to/my.csproj", """
55
+ <Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
56
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
57
+ <PropertyGroup>
58
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
59
+ </PropertyGroup>
60
+ <ItemGroup>
61
+ <None Include="packages.config" />
62
+ </ItemGroup>
63
+ <ItemGroup>
64
+ <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
65
+ <HintPath>packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
66
+ <Private>True</Private>
67
+ </Reference>
68
+ </ItemGroup>
69
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
70
+ </Project>
71
+ """),
72
+ ("path/to/packages.config", """
73
+ <packages>
74
+ <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
75
+ </packages>
76
+ """)
77
+ },
78
+ expectedResult: new()
79
+ {
80
+ FilePath = "",
81
+ Projects = [
82
+ new()
83
+ {
84
+ FilePath = "path/to/my.csproj",
85
+ TargetFrameworks = ["net45"],
86
+ ReferencedProjectPaths = [],
87
+ ExpectedDependencyCount = 2, // Should we ignore Microsoft.NET.ReferenceAssemblies?
88
+ Dependencies = [
89
+ new("Newtonsoft.Json", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"]),
90
+ ],
91
+ Properties = [
92
+ new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"),
93
+ ],
94
+ }
95
+ ]
96
+ });
97
+ }
98
+
99
+ [Fact]
100
+ public async Task WithProject()
101
+ {
102
+ var projectPath = "path/to/my.csproj";
103
+ await RunAsync(path =>
104
+ [
105
+ "discover",
106
+ "--repo-root",
107
+ path,
108
+ "--workspace",
109
+ path,
110
+ ],
111
+ new[]
112
+ {
113
+ (projectPath, """
114
+ <Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
115
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
116
+ <PropertyGroup>
117
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
118
+ </PropertyGroup>
119
+ <ItemGroup>
120
+ <None Include="packages.config" />
121
+ </ItemGroup>
122
+ <ItemGroup>
123
+ <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
124
+ <HintPath>packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
125
+ <Private>True</Private>
126
+ </Reference>
127
+ </ItemGroup>
128
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
129
+ </Project>
130
+ """),
131
+ ("path/to/packages.config", """
132
+ <packages>
133
+ <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
134
+ </packages>
135
+ """)
136
+ },
137
+ expectedResult: new()
138
+ {
139
+ FilePath = "",
140
+ Projects = [
141
+ new()
142
+ {
143
+ FilePath = projectPath,
144
+ TargetFrameworks = ["net45"],
145
+ ReferencedProjectPaths = [],
146
+ ExpectedDependencyCount = 2, // Should we ignore Microsoft.NET.ReferenceAssemblies?
147
+ Dependencies = [
148
+ new("Newtonsoft.Json", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"])
149
+ ],
150
+ Properties = [
151
+ new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"),
152
+ ],
153
+ }
154
+ ]
155
+ });
156
+ }
157
+
158
+ [Fact]
159
+ public async Task WithDirectory()
160
+ {
161
+ var workspacePath = "path/to/";
162
+ await RunAsync(path =>
163
+ [
164
+ "discover",
165
+ "--repo-root",
166
+ path,
167
+ "--workspace",
168
+ Path.Combine(path, workspacePath),
169
+ ],
170
+ new[]
171
+ {
172
+ ("path/to/my.csproj", """
173
+ <Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
174
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
175
+ <PropertyGroup>
176
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
177
+ </PropertyGroup>
178
+ <ItemGroup>
179
+ <None Include="packages.config" />
180
+ </ItemGroup>
181
+ <ItemGroup>
182
+ <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
183
+ <HintPath>packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
184
+ <Private>True</Private>
185
+ </Reference>
186
+ </ItemGroup>
187
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
188
+ </Project>
189
+ """),
190
+ ("path/to/packages.config", """
191
+ <packages>
192
+ <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
193
+ </packages>
194
+ """)
195
+ },
196
+ expectedResult: new()
197
+ {
198
+ FilePath = workspacePath,
199
+ Projects = [
200
+ new()
201
+ {
202
+ FilePath = "my.csproj",
203
+ TargetFrameworks = ["net45"],
204
+ ReferencedProjectPaths = [],
205
+ ExpectedDependencyCount = 2, // Should we ignore Microsoft.NET.ReferenceAssemblies?
206
+ Dependencies = [
207
+ new("Newtonsoft.Json", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"])
208
+ ],
209
+ Properties = [
210
+ new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"),
211
+ ],
212
+ }
213
+ ]
214
+ });
215
+ }
216
+
217
+ private static async Task RunAsync(
218
+ Func<string, string[]> getArgs,
219
+ TestFile[] initialFiles,
220
+ ExpectedWorkspaceDiscoveryResult expectedResult)
221
+ {
222
+ var actualResult = await RunDiscoveryAsync(initialFiles, async path =>
223
+ {
224
+ var sb = new StringBuilder();
225
+ var writer = new StringWriter(sb);
226
+
227
+ var originalOut = Console.Out;
228
+ var originalErr = Console.Error;
229
+ Console.SetOut(writer);
230
+ Console.SetError(writer);
231
+
232
+ try
233
+ {
234
+ var args = getArgs(path);
235
+ var result = await Program.Main(args);
236
+ if (result != 0)
237
+ {
238
+ throw new Exception($"Program exited with code {result}.\nOutput:\n\n{sb}");
239
+ }
240
+ }
241
+ finally
242
+ {
243
+ Console.SetOut(originalOut);
244
+ Console.SetError(originalErr);
245
+ }
246
+ });
247
+
248
+ ValidateWorkspaceResult(expectedResult, actualResult);
249
+ }
250
+ }
251
+ }
@@ -293,22 +293,30 @@ public partial class EntryPointTests
293
293
  );
294
294
  }
295
295
 
296
- [Fact]
297
- public async Task UpdaterDoesNotUseRepoGlobalJsonForMSBuildTasks()
296
+ [Theory]
297
+ [InlineData(null)]
298
+ [InlineData("src")]
299
+ public async Task UpdaterDoesNotUseRepoGlobalJsonForMSBuildTasks(string? workingDirectoryPath)
298
300
  {
299
301
  // This is a _very_ specific scenario where the `NuGetUpdater.Cli` tool might pick up a `global.json` from
300
302
  // the root of the repo under test and use it's `sdk` property when trying to locate MSBuild. To properly
301
303
  // test this, it must be tested in a new process where MSBuild has not been loaded yet and the runner tool
302
304
  // must be started with its working directory at the test repo's root.
303
305
  using var tempDir = new TemporaryDirectory();
304
- await File.WriteAllTextAsync(Path.Join(tempDir.DirectoryPath, "global.json"), """
306
+ var globalJsonPath = Path.Join(tempDir.DirectoryPath, "global.json");
307
+ var srcGlobalJsonPath = Path.Join(tempDir.DirectoryPath, "src", "global.json");
308
+ string globalJsonContent = """
305
309
  {
306
310
  "sdk": {
307
311
  "version": "99.99.99"
308
312
  }
309
313
  }
310
- """);
311
- await File.WriteAllTextAsync(Path.Join(tempDir.DirectoryPath, "project.csproj"), """
314
+ """;
315
+ await File.WriteAllTextAsync(globalJsonPath, globalJsonContent);
316
+ Directory.CreateDirectory(Path.Join(tempDir.DirectoryPath, "src"));
317
+ await File.WriteAllTextAsync(srcGlobalJsonPath, globalJsonContent);
318
+ var projectPath = Path.Join(tempDir.DirectoryPath, "src", "project.csproj");
319
+ await File.WriteAllTextAsync(projectPath, """
312
320
  <Project Sdk="Microsoft.NET.Sdk">
313
321
  <PropertyGroup>
314
322
  <TargetFramework>net8.0</TargetFramework>
@@ -325,7 +333,7 @@ public partial class EntryPointTests
325
333
  "--repo-root",
326
334
  tempDir.DirectoryPath,
327
335
  "--solution-or-project",
328
- Path.Join(tempDir.DirectoryPath, "project.csproj"),
336
+ projectPath,
329
337
  "--dependency",
330
338
  "Newtonsoft.Json",
331
339
  "--new-version",
@@ -336,15 +344,25 @@ public partial class EntryPointTests
336
344
  ]);
337
345
 
338
346
  // verify base run
339
- var (exitCode, output, error) = await ProcessEx.RunAsync(executableName, executableArgs, workingDirectory: tempDir.DirectoryPath);
347
+ var workingDirectory = tempDir.DirectoryPath;
348
+ if (workingDirectoryPath is not null)
349
+ {
350
+ workingDirectory = Path.Join(workingDirectory, workingDirectoryPath);
351
+ }
352
+
353
+ var (exitCode, output, error) = await ProcessEx.RunAsync(executableName, executableArgs, workingDirectory: workingDirectory);
340
354
  Assert.True(exitCode == 0, $"Error running update on unsupported SDK.\nSTDOUT:\n{output}\nSTDERR:\n{error}");
341
355
 
342
356
  // verify project update
343
- var updatedProjectContents = await File.ReadAllTextAsync(Path.Join(tempDir.DirectoryPath, "project.csproj"));
357
+ var updatedProjectContents = await File.ReadAllTextAsync(projectPath);
344
358
  Assert.Contains("13.0.1", updatedProjectContents);
345
359
 
346
360
  // verify `global.json` untouched
347
- var updatedGlobalJsonContents = await File.ReadAllTextAsync(Path.Join(tempDir.DirectoryPath, "global.json"));
361
+ var updatedGlobalJsonContents = await File.ReadAllTextAsync(globalJsonPath);
362
+ Assert.Contains("99.99.99", updatedGlobalJsonContents);
363
+
364
+ // verify `src/global.json` untouched
365
+ var updatedSrcGlobalJsonContents = await File.ReadAllTextAsync(srcGlobalJsonPath);
348
366
  Assert.Contains("99.99.99", updatedGlobalJsonContents);
349
367
  }
350
368
 
@@ -12,9 +12,9 @@
12
12
  </ItemGroup>
13
13
 
14
14
  <ItemGroup>
15
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
16
- <PackageReference Include="xunit" Version="2.4.2" />
17
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5" />
15
+ <PackageReference Include="Microsoft.NET.Test.Sdk" />
16
+ <PackageReference Include="xunit" />
17
+ <PackageReference Include="xunit.runner.visualstudio" />
18
18
  </ItemGroup>
19
19
 
20
20
  <ItemGroup>
@@ -1,3 +1,58 @@
1
+ using System.Collections.Immutable;
2
+
3
+ using NuGetUpdater.Core.Utilities;
4
+
1
5
  namespace NuGetUpdater.Core;
2
6
 
3
- public sealed record Dependency(string Name, string? Version, DependencyType Type, bool IsDevDependency = false, bool IsOverride = false, bool IsUpdate = false);
7
+ public sealed record Dependency(
8
+ string Name,
9
+ string? Version,
10
+ DependencyType Type,
11
+ EvaluationResult? EvaluationResult = null,
12
+ ImmutableArray<string>? TargetFrameworks = null,
13
+ bool IsDevDependency = false,
14
+ bool IsDirect = false,
15
+ bool IsTransitive = false,
16
+ bool IsOverride = false,
17
+ bool IsUpdate = false) : IEquatable<Dependency>
18
+ {
19
+ public bool Equals(Dependency? other)
20
+ {
21
+ if (other is null)
22
+ {
23
+ return false;
24
+ }
25
+
26
+ if (ReferenceEquals(this, other))
27
+ {
28
+ return true;
29
+ }
30
+
31
+ return Name == other.Name &&
32
+ Version == other.Version &&
33
+ Type == other.Type &&
34
+ EvaluationResult == other.EvaluationResult &&
35
+ TargetFrameworks.SequenceEqual(other.TargetFrameworks) &&
36
+ IsDevDependency == other.IsDevDependency &&
37
+ IsDirect == other.IsDirect &&
38
+ IsTransitive == other.IsTransitive &&
39
+ IsOverride == other.IsOverride &&
40
+ IsUpdate == other.IsUpdate;
41
+ }
42
+
43
+ public override int GetHashCode()
44
+ {
45
+ HashCode hash = new();
46
+ hash.Add(Name);
47
+ hash.Add(Version);
48
+ hash.Add(Type);
49
+ hash.Add(EvaluationResult);
50
+ hash.Add(TargetFrameworks);
51
+ hash.Add(IsDevDependency);
52
+ hash.Add(IsDirect);
53
+ hash.Add(IsTransitive);
54
+ hash.Add(IsOverride);
55
+ hash.Add(IsUpdate);
56
+ return hash.ToHashCode();
57
+ }
58
+ }
@@ -3,7 +3,7 @@ namespace NuGetUpdater.Core;
3
3
  public enum DependencyType
4
4
  {
5
5
  Unknown,
6
- PackageConfig,
6
+ PackagesConfig,
7
7
  PackageReference,
8
8
  PackageVersion,
9
9
  GlobalPackageReference,
@@ -0,0 +1,69 @@
1
+ using System.Collections.Immutable;
2
+
3
+ namespace NuGetUpdater.Core.Discover;
4
+
5
+ internal static class DirectoryPackagesPropsDiscovery
6
+ {
7
+ public static DirectoryPackagesPropsDiscoveryResult? Discover(string repoRootPath, string workspacePath, ImmutableArray<ProjectDiscoveryResult> projectResults, Logger logger)
8
+ {
9
+ var projectResult = projectResults.FirstOrDefault(
10
+ p => p.Properties.FirstOrDefault(prop => prop.Name.Equals("ManagePackageVersionsCentrally", StringComparison.OrdinalIgnoreCase)) is Property property
11
+ && string.Equals(property.Value, "true", StringComparison.OrdinalIgnoreCase));
12
+ if (projectResult is null)
13
+ {
14
+ logger.Log(" Central Package Management is not enabled.");
15
+ return null;
16
+ }
17
+
18
+ var projectFilePath = Path.GetFullPath(projectResult.FilePath, workspacePath);
19
+ if (!MSBuildHelper.TryGetDirectoryPackagesPropsPath(repoRootPath, projectFilePath, out var directoryPackagesPropsPath))
20
+ {
21
+ logger.Log(" No Directory.Packages.props file found.");
22
+ return null;
23
+ }
24
+
25
+ var relativeDirectoryPackagesPropsPath = Path.GetRelativePath(workspacePath, directoryPackagesPropsPath);
26
+ var directoryPackagesPropsFile = projectResults.FirstOrDefault(p => p.FilePath.Equals(relativeDirectoryPackagesPropsPath, StringComparison.OrdinalIgnoreCase));
27
+ if (directoryPackagesPropsFile is null)
28
+ {
29
+ logger.Log($" No project file found for [{relativeDirectoryPackagesPropsPath}].");
30
+ return null;
31
+ }
32
+
33
+ logger.Log($" Discovered [{directoryPackagesPropsFile.FilePath}] file.");
34
+
35
+ var isTransitivePinningEnabled = projectResult.Properties.FirstOrDefault(prop => prop.Name.Equals("EnableTransitivePinning", StringComparison.OrdinalIgnoreCase)) is Property property
36
+ && string.Equals(property.Value, "true", StringComparison.OrdinalIgnoreCase);
37
+ var properties = projectResult.Properties.ToImmutableDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase);
38
+ var dependencies = GetDependencies(workspacePath, directoryPackagesPropsPath, properties)
39
+ .OrderBy(d => d.Name)
40
+ .ToImmutableArray();
41
+
42
+ return new()
43
+ {
44
+ FilePath = directoryPackagesPropsFile.FilePath,
45
+ IsTransitivePinningEnabled = isTransitivePinningEnabled,
46
+ Dependencies = dependencies,
47
+ };
48
+ }
49
+
50
+ private static IEnumerable<Dependency> GetDependencies(string workspacePath, string directoryPackagesPropsPath, ImmutableDictionary<string, Property> properties)
51
+ {
52
+ var dependencies = ProjectBuildFile.Open(workspacePath, directoryPackagesPropsPath).GetDependencies();
53
+ return dependencies.Select(d =>
54
+ {
55
+ if (d.Version == null)
56
+ {
57
+ return d;
58
+ }
59
+
60
+ var evaluation = MSBuildHelper.GetEvaluatedValue(d.Version, properties);
61
+ return d with
62
+ {
63
+ Version = evaluation.EvaluatedValue,
64
+ EvaluationResult = evaluation,
65
+ IsDirect = true,
66
+ };
67
+ });
68
+ }
69
+ }
@@ -0,0 +1,11 @@
1
+ using System.Collections.Immutable;
2
+
3
+ namespace NuGetUpdater.Core.Discover;
4
+
5
+ public sealed record DirectoryPackagesPropsDiscoveryResult : IDiscoveryResultWithDependencies
6
+ {
7
+ public required string FilePath { get; init; }
8
+ public bool IsSuccess { get; init; } = true;
9
+ public bool IsTransitivePinningEnabled { get; init; }
10
+ public ImmutableArray<Dependency> Dependencies { get; init; }
11
+ }