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.
- checksums.yaml +4 -4
- data/helpers/lib/NuGetUpdater/Directory.Common.props +1 -0
- data/helpers/lib/NuGetUpdater/Directory.Packages.props +26 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +35 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/NuGetUpdater.Cli.csproj +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Program.cs +4 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +251 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +27 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/NuGetUpdater.Cli.Test.csproj +3 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Dependency.cs +56 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyType.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscovery.cs +69 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscoveryResult.cs +11 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +217 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DotNetToolsJsonDiscovery.cs +30 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DotNetToolsJsonDiscoveryResult.cs +10 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/GlobalJsonDiscovery.cs +30 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/GlobalJsonDiscoveryResult.cs +10 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/IDiscoveryResult.cs +14 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +29 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscoveryResult.cs +10 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +13 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +128 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +13 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/EvaluationResult.cs +8 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/EvaluationResultType.cs +9 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/BuildFile.cs +6 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/DotNetToolsJsonBuildFile.cs +4 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/GlobalJsonBuildFile.cs +24 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/JsonBuildFile.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/PackagesConfigBuildFile.cs +8 -13
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/ProjectBuildFile.cs +100 -19
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/XmlBuildFile.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +6 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Property.cs +6 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/DotNetToolsJsonUpdater.cs +23 -36
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/GlobalJsonUpdater.cs +5 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +59 -26
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +5 -20
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/HashSetExtensions.cs +14 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ImmutableArrayExtensions.cs +18 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/JsonHelper.cs +0 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +281 -140
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +27 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +18 -13
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +135 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs +91 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs +71 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +67 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +405 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +306 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +36 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/DotNetToolsJsonBuildFileTests.cs +1 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/GlobalJsonBuildFileTests.cs +2 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/PackagesConfigBuildFileTests.cs +4 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/ProjectBuildFileTests.cs +6 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/NuGetUpdater.Core.Test.csproj +4 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryDirectory.cs +38 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestBase.cs +10 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackagesConfigUpdaterTests.cs +1 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +13 -41
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs +0 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs +0 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs +0 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +0 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +0 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +30 -23
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/AssertEx.cs +272 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/DiffUtil.cs +266 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +239 -161
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/SdkPackageUpdaterHelperTests.cs +7 -11
- data/lib/dependabot/nuget/discovery/dependency_details.rb +95 -0
- data/lib/dependabot/nuget/discovery/dependency_file_discovery.rb +126 -0
- data/lib/dependabot/nuget/discovery/directory_packages_props_discovery.rb +43 -0
- data/lib/dependabot/nuget/discovery/discovery_json_reader.rb +83 -0
- data/lib/dependabot/nuget/discovery/evaluation_details.rb +63 -0
- data/lib/dependabot/nuget/discovery/project_discovery.rb +71 -0
- data/lib/dependabot/nuget/discovery/property_details.rb +43 -0
- data/lib/dependabot/nuget/discovery/workspace_discovery.rb +66 -0
- data/lib/dependabot/nuget/file_parser.rb +19 -128
- data/lib/dependabot/nuget/file_updater.rb +28 -60
- data/lib/dependabot/nuget/native_helpers.rb +55 -0
- data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +3 -8
- data/lib/dependabot/nuget/update_checker/dependency_finder.rb +1 -0
- data/lib/dependabot/nuget/update_checker/property_updater.rb +1 -0
- data/lib/dependabot/nuget/update_checker/tfm_finder.rb +17 -152
- data/lib/dependabot/nuget/update_checker/version_finder.rb +1 -6
- data/lib/dependabot/nuget/update_checker.rb +4 -1
- metadata +44 -25
- data/lib/dependabot/nuget/file_parser/dotnet_tools_json_parser.rb +0 -71
- data/lib/dependabot/nuget/file_parser/global_json_parser.rb +0 -68
- data/lib/dependabot/nuget/file_parser/packages_config_parser.rb +0 -92
- data/lib/dependabot/nuget/file_parser/project_file_parser.rb +0 -620
- data/lib/dependabot/nuget/file_parser/property_value_finder.rb +0 -225
- data/lib/dependabot/nuget/file_updater/property_value_updater.rb +0 -81
data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/SdkPackageUpdaterHelperTests.cs
CHANGED
@@ -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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
175
|
-
var buildFilePaths = buildFiles.Select(f => f.
|
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
|