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
@@ -1,7 +1,3 @@
1
- using System.IO;
2
- using System.Linq;
3
- using System.Threading.Tasks;
4
-
5
1
  using Xunit;
6
2
 
7
3
  namespace NuGetUpdater.Core.Test.Utilities
@@ -11,7 +7,7 @@ namespace NuGetUpdater.Core.Test.Utilities
11
7
  [Fact]
12
8
  public async Task DirectoryBuildFilesAreOnlyPulledInFromParentDirectories()
13
9
  {
14
- using var temporaryDirectory = TemporaryDirectory.CreateWithContents(
10
+ using var temporaryDirectory = await TemporaryDirectory.CreateWithContentsAsync(
15
11
  ("src/SomeProject.csproj", """
16
12
  <Project Sdk="Microsoft.NET.Sdk">
17
13
  <Import Project="..\props\Versions.props" />
@@ -52,7 +48,7 @@ namespace NuGetUpdater.Core.Test.Utilities
52
48
  [InlineData("src/", "")] // project in subdirectory, global.json at root
53
49
  public async Task BuildFileEnumerationWorksEvenWithNonSupportedSdkInGlobalJson(string projectSubpath, string globalJsonSubpath)
54
50
  {
55
- using var temporaryDirectory = TemporaryDirectory.CreateWithContents(
51
+ using var temporaryDirectory = await TemporaryDirectory.CreateWithContentsAsync(
56
52
  ($"{projectSubpath}SomeProject.csproj", """
57
53
  <Project Sdk="Microsoft.NET.Sdk">
58
54
  </Project>
@@ -82,7 +78,7 @@ namespace NuGetUpdater.Core.Test.Utilities
82
78
  [Fact]
83
79
  public async Task BuildFileEnumerationWithNonStandardMSBuildSdkAndNonSupportedSdkVersionInGlobalJson()
84
80
  {
85
- using var temporaryDirectory = TemporaryDirectory.CreateWithContents(
81
+ using var temporaryDirectory = await TemporaryDirectory.CreateWithContentsAsync(
86
82
  ("global.json", """
87
83
  {
88
84
  "sdk": {
@@ -123,7 +119,7 @@ namespace NuGetUpdater.Core.Test.Utilities
123
119
  [Fact]
124
120
  public async Task BuildFileEnumerationWithUnsuccessfulImport()
125
121
  {
126
- using var temporaryDirectory = TemporaryDirectory.CreateWithContents(
122
+ using var temporaryDirectory = await TemporaryDirectory.CreateWithContentsAsync(
127
123
  ("Directory.Build.props", """
128
124
  <Project>
129
125
  <Import Project="file-that-does-not-exist.targets" />
@@ -146,7 +142,7 @@ namespace NuGetUpdater.Core.Test.Utilities
146
142
  [Fact]
147
143
  public async Task BuildFileEnumerationWithGlobalJsonWithComments()
148
144
  {
149
- using var temporaryDirectory = TemporaryDirectory.CreateWithContents(
145
+ using var temporaryDirectory = await TemporaryDirectory.CreateWithContentsAsync(
150
146
  ("global.json", """
151
147
  {
152
148
  // this is a comment
@@ -171,8 +167,8 @@ namespace NuGetUpdater.Core.Test.Utilities
171
167
 
172
168
  private static async Task<string[]> LoadBuildFilesFromTemp(TemporaryDirectory temporaryDirectory, string relativeProjectPath)
173
169
  {
174
- var buildFiles = await MSBuildHelper.LoadBuildFiles(temporaryDirectory.DirectoryPath, $"{temporaryDirectory.DirectoryPath}/{relativeProjectPath}");
175
- var buildFilePaths = buildFiles.Select(f => f.RepoRelativePath.NormalizePathToUnix()).ToArray();
170
+ var (buildFiles, _tfms) = await MSBuildHelper.LoadBuildFilesAndTargetFrameworksAsync(temporaryDirectory.DirectoryPath, $"{temporaryDirectory.DirectoryPath}/{relativeProjectPath}");
171
+ var buildFilePaths = buildFiles.Select(f => f.RelativePath.NormalizePathToUnix()).ToArray();
176
172
  return buildFilePaths;
177
173
  }
178
174
  }
@@ -0,0 +1,95 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "dependabot/nuget/discovery/evaluation_details"
5
+ require "sorbet-runtime"
6
+
7
+ module Dependabot
8
+ module Nuget
9
+ class DependencyDetails
10
+ extend T::Sig
11
+
12
+ sig { params(json: T::Hash[String, T.untyped]).returns(DependencyDetails) }
13
+ def self.from_json(json)
14
+ name = T.let(json.fetch("Name"), String)
15
+ version = T.let(json.fetch("Version"), T.nilable(String))
16
+ type = T.let(json.fetch("Type"), String)
17
+ evaluation = EvaluationDetails
18
+ .from_json(T.let(json.fetch("EvaluationResult"), T.nilable(T::Hash[String, T.untyped])))
19
+ target_frameworks = T.let(json.fetch("TargetFrameworks"), T.nilable(T::Array[String]))
20
+ is_dev_dependency = T.let(json.fetch("IsDevDependency"), T::Boolean)
21
+ is_direct = T.let(json.fetch("IsDirect"), T::Boolean)
22
+ is_transitive = T.let(json.fetch("IsTransitive"), T::Boolean)
23
+ is_override = T.let(json.fetch("IsOverride"), T::Boolean)
24
+ is_update = T.let(json.fetch("IsUpdate"), T::Boolean)
25
+
26
+ DependencyDetails.new(name: name,
27
+ version: version,
28
+ type: type,
29
+ evaluation: evaluation,
30
+ target_frameworks: target_frameworks,
31
+ is_dev_dependency: is_dev_dependency,
32
+ is_direct: is_direct,
33
+ is_transitive: is_transitive,
34
+ is_override: is_override,
35
+ is_update: is_update)
36
+ end
37
+
38
+ sig do
39
+ params(name: String,
40
+ version: T.nilable(String),
41
+ type: String,
42
+ evaluation: T.nilable(EvaluationDetails),
43
+ target_frameworks: T.nilable(T::Array[String]),
44
+ is_dev_dependency: T::Boolean,
45
+ is_direct: T::Boolean,
46
+ is_transitive: T::Boolean,
47
+ is_override: T::Boolean,
48
+ is_update: T::Boolean).void
49
+ end
50
+ def initialize(name:, version:, type:, evaluation:, target_frameworks:, is_dev_dependency:, is_direct:,
51
+ is_transitive:, is_override:, is_update:)
52
+ @name = name
53
+ @version = version
54
+ @type = type
55
+ @evaluation = evaluation
56
+ @target_frameworks = target_frameworks
57
+ @is_dev_dependency = is_dev_dependency
58
+ @is_direct = is_direct
59
+ @is_transitive = is_transitive
60
+ @is_override = is_override
61
+ @is_update = is_update
62
+ end
63
+
64
+ sig { returns(String) }
65
+ attr_reader :name
66
+
67
+ sig { returns(T.nilable(String)) }
68
+ attr_reader :version
69
+
70
+ sig { returns(String) }
71
+ attr_reader :type
72
+
73
+ sig { returns(T.nilable(EvaluationDetails)) }
74
+ attr_reader :evaluation
75
+
76
+ sig { returns(T.nilable(T::Array[String])) }
77
+ attr_reader :target_frameworks
78
+
79
+ sig { returns(T::Boolean) }
80
+ attr_reader :is_dev_dependency
81
+
82
+ sig { returns(T::Boolean) }
83
+ attr_reader :is_direct
84
+
85
+ sig { returns(T::Boolean) }
86
+ attr_reader :is_transitive
87
+
88
+ sig { returns(T::Boolean) }
89
+ attr_reader :is_override
90
+
91
+ sig { returns(T::Boolean) }
92
+ attr_reader :is_update
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,126 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "dependabot/nuget/discovery/dependency_details"
5
+ require "sorbet-runtime"
6
+
7
+ module Dependabot
8
+ module Nuget
9
+ class DependencyFileDiscovery
10
+ extend T::Sig
11
+
12
+ sig { params(json: T.nilable(T::Hash[String, T.untyped])).returns(T.nilable(DependencyFileDiscovery)) }
13
+ def self.from_json(json)
14
+ return nil if json.nil?
15
+
16
+ file_path = T.let(json.fetch("FilePath"), String)
17
+ dependencies = T.let(json.fetch("Dependencies"), T::Array[T::Hash[String, T.untyped]]).map do |dep|
18
+ DependencyDetails.from_json(dep)
19
+ end
20
+
21
+ DependencyFileDiscovery.new(file_path: file_path,
22
+ dependencies: dependencies)
23
+ end
24
+
25
+ sig do
26
+ params(file_path: String,
27
+ dependencies: T::Array[DependencyDetails]).void
28
+ end
29
+ def initialize(file_path:, dependencies:)
30
+ @file_path = file_path
31
+ @dependencies = dependencies
32
+ end
33
+
34
+ sig { returns(String) }
35
+ attr_reader :file_path
36
+
37
+ sig { returns(T::Array[DependencyDetails]) }
38
+ attr_reader :dependencies
39
+
40
+ sig { overridable.returns(Dependabot::FileParsers::Base::DependencySet) }
41
+ def dependency_set # rubocop:disable Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/AbcSize
42
+ dependency_set = Dependabot::FileParsers::Base::DependencySet.new
43
+
44
+ file_name = Pathname.new(file_path).cleanpath.to_path
45
+ dependencies.each do |dependency|
46
+ next if dependency.name.casecmp("Microsoft.NET.Sdk")&.zero?
47
+
48
+ # If the version string was evaluated it must have been successfully resolved
49
+ if dependency.evaluation && dependency.evaluation&.result_type != "Success"
50
+ logger.warn "Dependency '#{dependency.name}' excluded due to unparsable version: #{dependency.version}"
51
+ next
52
+ end
53
+
54
+ # Exclude any dependencies using version ranges or wildcards
55
+ next if dependency.version&.include?(",") ||
56
+ dependency.version&.include?("*")
57
+
58
+ # Exclude any dependencies specified using interpolation
59
+ next if dependency.name.include?("%(") ||
60
+ dependency.version&.include?("%(")
61
+
62
+ # Exclude any dependencies which reference an item type
63
+ next if dependency.name.include?("@(")
64
+
65
+ dependency_file_name = file_name
66
+ if dependency.type == "PackagesConfig"
67
+ dir_name = File.dirname(file_name)
68
+ dependency_file_name = "packages.config"
69
+ dependency_file_name = File.join(dir_name, "packages.config") unless dir_name == "."
70
+ end
71
+
72
+ dependency_set << build_dependency(dependency_file_name, dependency)
73
+ end
74
+
75
+ dependency_set
76
+ end
77
+
78
+ private
79
+
80
+ sig { returns(::Logger) }
81
+ def logger
82
+ Dependabot.logger
83
+ end
84
+
85
+ sig { params(file_name: String, dependency_details: DependencyDetails).returns(Dependabot::Dependency) }
86
+ def build_dependency(file_name, dependency_details)
87
+ requirement = build_requirement(file_name, dependency_details)
88
+ requirements = requirement.nil? ? [] : [requirement]
89
+
90
+ version = dependency_details.version&.gsub(/[\(\)\[\]]/, "")&.strip
91
+ version = nil if version&.empty?
92
+
93
+ Dependency.new(
94
+ name: dependency_details.name,
95
+ version: version,
96
+ package_manager: "nuget",
97
+ requirements: requirements
98
+ )
99
+ end
100
+
101
+ sig do
102
+ params(file_name: String, dependency_details: DependencyDetails)
103
+ .returns(T.nilable(T::Hash[Symbol, T.untyped]))
104
+ end
105
+ def build_requirement(file_name, dependency_details)
106
+ return if dependency_details.is_transitive
107
+
108
+ version = dependency_details.version
109
+ version = nil if version&.empty?
110
+
111
+ requirement = {
112
+ requirement: version,
113
+ file: file_name,
114
+ groups: [dependency_details.is_dev_dependency ? "devDependencies" : "dependencies"],
115
+ source: nil
116
+ }
117
+
118
+ property_name = dependency_details.evaluation&.root_property_name
119
+ return requirement unless property_name
120
+
121
+ requirement[:metadata] = { property_name: property_name }
122
+ requirement
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,43 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "dependabot/nuget/discovery/dependency_details"
5
+ require "sorbet-runtime"
6
+
7
+ module Dependabot
8
+ module Nuget
9
+ class DirectoryPackagesPropsDiscovery < DependencyFileDiscovery
10
+ extend T::Sig
11
+
12
+ sig do
13
+ params(json: T.nilable(T::Hash[String, T.untyped])).returns(T.nilable(DirectoryPackagesPropsDiscovery))
14
+ end
15
+ def self.from_json(json)
16
+ return nil if json.nil?
17
+
18
+ file_path = T.let(json.fetch("FilePath"), String)
19
+ is_transitive_pinning_enabled = T.let(json.fetch("IsTransitivePinningEnabled"), T::Boolean)
20
+ dependencies = T.let(json.fetch("Dependencies"), T::Array[T::Hash[String, T.untyped]]).map do |dep|
21
+ DependencyDetails.from_json(dep)
22
+ end
23
+
24
+ DirectoryPackagesPropsDiscovery.new(file_path: file_path,
25
+ is_transitive_pinning_enabled: is_transitive_pinning_enabled,
26
+ dependencies: dependencies)
27
+ end
28
+
29
+ sig do
30
+ params(file_path: String,
31
+ is_transitive_pinning_enabled: T::Boolean,
32
+ dependencies: T::Array[DependencyDetails]).void
33
+ end
34
+ def initialize(file_path:, is_transitive_pinning_enabled:, dependencies:)
35
+ super(file_path: file_path, dependencies: dependencies)
36
+ @is_transitive_pinning_enabled = is_transitive_pinning_enabled
37
+ end
38
+
39
+ sig { returns(T::Boolean) }
40
+ attr_reader :is_transitive_pinning_enabled
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,83 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "dependabot/dependency"
5
+ require "dependabot/nuget/discovery/workspace_discovery"
6
+ require "json"
7
+ require "sorbet-runtime"
8
+
9
+ module Dependabot
10
+ module Nuget
11
+ class DiscoveryJsonReader
12
+ extend T::Sig
13
+
14
+ DISCOVERY_JSON_PATH = ".dependabot/discovery.json"
15
+
16
+ sig { returns(String) }
17
+ private_class_method def self.temp_directory
18
+ Dir.tmpdir
19
+ end
20
+
21
+ sig { returns(String) }
22
+ def self.discovery_file_path
23
+ File.join(temp_directory, DISCOVERY_JSON_PATH)
24
+ end
25
+
26
+ sig { returns(T.nilable(DependencyFile)) }
27
+ def self.discovery_json
28
+ return unless File.exist?(discovery_file_path)
29
+
30
+ DependencyFile.new(
31
+ name: Pathname.new(discovery_file_path).cleanpath.to_path,
32
+ directory: temp_directory,
33
+ type: "file",
34
+ content: File.read(discovery_file_path)
35
+ )
36
+ end
37
+
38
+ sig { params(discovery_json: DependencyFile).void }
39
+ def initialize(discovery_json:)
40
+ @discovery_json = discovery_json
41
+ end
42
+
43
+ sig { returns(Dependabot::FileParsers::Base::DependencySet) }
44
+ def dependency_set
45
+ dependency_set = Dependabot::FileParsers::Base::DependencySet.new
46
+ return dependency_set unless workspace_discovery
47
+
48
+ workspace_result = T.must(workspace_discovery)
49
+ workspace_result.projects.each do |project|
50
+ dependency_set += project.dependency_set
51
+ end
52
+ if workspace_result.directory_packages_props
53
+ dependency_set += T.must(workspace_result.directory_packages_props).dependency_set
54
+ end
55
+ if workspace_result.dotnet_tools_json
56
+ dependency_set += T.must(workspace_result.dotnet_tools_json).dependency_set
57
+ end
58
+ dependency_set += T.must(workspace_result.global_json).dependency_set if workspace_result.global_json
59
+
60
+ dependency_set
61
+ end
62
+
63
+ sig { returns(T.nilable(WorkspaceDiscovery)) }
64
+ def workspace_discovery
65
+ @workspace_discovery ||= T.let(begin
66
+ return nil unless discovery_json.content
67
+
68
+ Dependabot.logger.info("Discovery JSON content: #{discovery_json.content}")
69
+
70
+ parsed_json = T.let(JSON.parse(T.must(discovery_json.content)), T::Hash[String, T.untyped])
71
+ WorkspaceDiscovery.from_json(parsed_json)
72
+ end, T.nilable(WorkspaceDiscovery))
73
+ rescue JSON::ParserError
74
+ raise Dependabot::DependencyFileNotParseable, discovery_json.path
75
+ end
76
+
77
+ private
78
+
79
+ sig { returns(DependencyFile) }
80
+ attr_reader :discovery_json
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,63 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet-runtime"
5
+
6
+ module Dependabot
7
+ module Nuget
8
+ class EvaluationDetails
9
+ extend T::Sig
10
+
11
+ sig { params(json: T.nilable(T::Hash[String, T.untyped])).returns(T.nilable(EvaluationDetails)) }
12
+ def self.from_json(json)
13
+ return nil if json.nil?
14
+
15
+ result_type = T.let(json.fetch("ResultType"), String)
16
+ original_value = T.let(json.fetch("OriginalValue"), String)
17
+ evaluated_value = T.let(json.fetch("EvaluatedValue"), String)
18
+ root_property_name = T.let(json.fetch("RootPropertyName", nil), T.nilable(String))
19
+ error_message = T.let(json.fetch("ErrorMessage", nil), T.nilable(String))
20
+
21
+ EvaluationDetails.new(result_type: result_type,
22
+ original_value: original_value,
23
+ evaluated_value: evaluated_value,
24
+ root_property_name: root_property_name,
25
+ error_message: error_message)
26
+ end
27
+
28
+ sig do
29
+ params(result_type: String,
30
+ original_value: String,
31
+ evaluated_value: String,
32
+ root_property_name: T.nilable(String),
33
+ error_message: T.nilable(String)).void
34
+ end
35
+ def initialize(result_type:,
36
+ original_value:,
37
+ evaluated_value:,
38
+ root_property_name:,
39
+ error_message:)
40
+ @result_type = result_type
41
+ @original_value = original_value
42
+ @evaluated_value = evaluated_value
43
+ @root_property_name = root_property_name
44
+ @error_message = error_message
45
+ end
46
+
47
+ sig { returns(String) }
48
+ attr_reader :result_type
49
+
50
+ sig { returns(String) }
51
+ attr_reader :original_value
52
+
53
+ sig { returns(String) }
54
+ attr_reader :evaluated_value
55
+
56
+ sig { returns(T.nilable(String)) }
57
+ attr_reader :root_property_name
58
+
59
+ sig { returns(T.nilable(String)) }
60
+ attr_reader :error_message
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,71 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "dependabot/nuget/discovery/dependency_details"
5
+ require "dependabot/nuget/discovery/property_details"
6
+ require "sorbet-runtime"
7
+
8
+ module Dependabot
9
+ module Nuget
10
+ class ProjectDiscovery < DependencyFileDiscovery
11
+ extend T::Sig
12
+
13
+ sig do
14
+ params(json: T.nilable(T::Hash[String, T.untyped])).returns(T.nilable(ProjectDiscovery))
15
+ end
16
+ def self.from_json(json)
17
+ return nil if json.nil?
18
+
19
+ file_path = T.let(json.fetch("FilePath"), String)
20
+ properties = T.let(json.fetch("Properties"), T::Array[T::Hash[String, T.untyped]]).map do |prop|
21
+ PropertyDetails.from_json(prop)
22
+ end
23
+ target_frameworks = T.let(json.fetch("TargetFrameworks"), T::Array[String])
24
+ referenced_project_paths = T.let(json.fetch("ReferencedProjectPaths"), T::Array[String])
25
+ dependencies = T.let(json.fetch("Dependencies"), T::Array[T::Hash[String, T.untyped]]).map do |dep|
26
+ DependencyDetails.from_json(dep)
27
+ end
28
+
29
+ ProjectDiscovery.new(file_path: file_path,
30
+ properties: properties,
31
+ target_frameworks: target_frameworks,
32
+ referenced_project_paths: referenced_project_paths,
33
+ dependencies: dependencies)
34
+ end
35
+
36
+ sig do
37
+ params(file_path: String,
38
+ properties: T::Array[PropertyDetails],
39
+ target_frameworks: T::Array[String],
40
+ referenced_project_paths: T::Array[String],
41
+ dependencies: T::Array[DependencyDetails]).void
42
+ end
43
+ def initialize(file_path:, properties:, target_frameworks:, referenced_project_paths:, dependencies:)
44
+ super(file_path: file_path, dependencies: dependencies)
45
+ @properties = properties
46
+ @target_frameworks = target_frameworks
47
+ @referenced_project_paths = referenced_project_paths
48
+ end
49
+
50
+ sig { returns(T::Array[PropertyDetails]) }
51
+ attr_reader :properties
52
+
53
+ sig { returns(T::Array[String]) }
54
+ attr_reader :target_frameworks
55
+
56
+ sig { returns(T::Array[String]) }
57
+ attr_reader :referenced_project_paths
58
+
59
+ sig { override.returns(Dependabot::FileParsers::Base::DependencySet) }
60
+ def dependency_set
61
+ if target_frameworks.empty? && file_path.end_with?("proj")
62
+ Dependabot.logger.warn("Excluding project file '#{file_path}' due to unresolvable target framework")
63
+ dependency_set = Dependabot::FileParsers::Base::DependencySet.new
64
+ return dependency_set
65
+ end
66
+
67
+ super
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,43 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet-runtime"
5
+
6
+ module Dependabot
7
+ module Nuget
8
+ class PropertyDetails
9
+ extend T::Sig
10
+
11
+ sig { params(json: T::Hash[String, T.untyped]).returns(PropertyDetails) }
12
+ def self.from_json(json)
13
+ name = T.let(json.fetch("Name"), String)
14
+ value = T.let(json.fetch("Value"), String)
15
+ source_file_path = T.let(json.fetch("SourceFilePath"), String)
16
+
17
+ PropertyDetails.new(name: name,
18
+ value: value,
19
+ source_file_path: source_file_path)
20
+ end
21
+
22
+ sig do
23
+ params(name: String,
24
+ value: String,
25
+ source_file_path: String).void
26
+ end
27
+ def initialize(name:, value:, source_file_path:)
28
+ @name = name
29
+ @value = value
30
+ @source_file_path = source_file_path
31
+ end
32
+
33
+ sig { returns(String) }
34
+ attr_reader :name
35
+
36
+ sig { returns(String) }
37
+ attr_reader :value
38
+
39
+ sig { returns(String) }
40
+ attr_reader :source_file_path
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,66 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "dependabot/nuget/discovery/dependency_file_discovery"
5
+ require "dependabot/nuget/discovery/directory_packages_props_discovery"
6
+ require "dependabot/nuget/discovery/project_discovery"
7
+ require "sorbet-runtime"
8
+
9
+ module Dependabot
10
+ module Nuget
11
+ class WorkspaceDiscovery
12
+ extend T::Sig
13
+
14
+ sig { params(json: T::Hash[String, T.untyped]).returns(WorkspaceDiscovery) }
15
+ def self.from_json(json)
16
+ file_path = T.let(json.fetch("FilePath"), String)
17
+ projects = T.let(json.fetch("Projects"), T::Array[T::Hash[String, T.untyped]]).filter_map do |project|
18
+ ProjectDiscovery.from_json(project)
19
+ end
20
+ directory_packages_props = DirectoryPackagesPropsDiscovery
21
+ .from_json(T.let(json.fetch("DirectoryPackagesProps"),
22
+ T.nilable(T::Hash[String, T.untyped])))
23
+ global_json = DependencyFileDiscovery
24
+ .from_json(T.let(json.fetch("GlobalJson"), T.nilable(T::Hash[String, T.untyped])))
25
+ dotnet_tools_json = DependencyFileDiscovery
26
+ .from_json(T.let(json.fetch("DotNetToolsJson"), T.nilable(T::Hash[String, T.untyped])))
27
+
28
+ WorkspaceDiscovery.new(file_path: file_path,
29
+ projects: projects,
30
+ directory_packages_props: directory_packages_props,
31
+ global_json: global_json,
32
+ dotnet_tools_json: dotnet_tools_json)
33
+ end
34
+
35
+ sig do
36
+ params(file_path: String,
37
+ projects: T::Array[ProjectDiscovery],
38
+ directory_packages_props: T.nilable(DirectoryPackagesPropsDiscovery),
39
+ global_json: T.nilable(DependencyFileDiscovery),
40
+ dotnet_tools_json: T.nilable(DependencyFileDiscovery)).void
41
+ end
42
+ def initialize(file_path:, projects:, directory_packages_props:, global_json:, dotnet_tools_json:)
43
+ @file_path = file_path
44
+ @projects = projects
45
+ @directory_packages_props = directory_packages_props
46
+ @global_json = global_json
47
+ @dotnet_tools_json = dotnet_tools_json
48
+ end
49
+
50
+ sig { returns(String) }
51
+ attr_reader :file_path
52
+
53
+ sig { returns(T::Array[ProjectDiscovery]) }
54
+ attr_reader :projects
55
+
56
+ sig { returns(T.nilable(DirectoryPackagesPropsDiscovery)) }
57
+ attr_reader :directory_packages_props
58
+
59
+ sig { returns(T.nilable(DependencyFileDiscovery)) }
60
+ attr_reader :global_json
61
+
62
+ sig { returns(T.nilable(DependencyFileDiscovery)) }
63
+ attr_reader :dotnet_tools_json
64
+ end
65
+ end
66
+ end