dependabot-nuget 0.288.0 → 0.290.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.Packages.props +19 -17
- data/helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Packaging/NuGet.Packaging.csproj +0 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/AnalyzeCommand.cs +7 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +29 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +25 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Run.cs +0 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +33 -16
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +25 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/NuGetContext.cs +0 -13
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementArrayConverter.cs +39 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Clone/ShellGitCommandHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +60 -66
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DotNetToolsJsonDiscovery.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/GlobalJsonDiscovery.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +11 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscoveryResult.cs +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +2 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +54 -11
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +0 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +1 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/JsonBuildFile.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/CompatabilityChecker.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Advisory.cs +13 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/AllowedUpdate.cs +18 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/CommitOptions.cs +8 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Condition.cs +19 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyGroup.cs +8 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/GroupPullRequest.cs +9 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Job.cs +13 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/PullRequest.cs +11 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/RequirementsUpdateStrategy.cs +15 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +67 -58
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/VersionConverter.cs +19 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +15 -44
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/DotNetToolsJsonUpdater.cs +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/GlobalJsonUpdater.cs +5 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +2 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +38 -33
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +25 -23
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +16 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ConsoleLogger.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DependencyConflictResolver.cs +19 -19
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ILogger.cs +11 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/JsonHelper.cs +2 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +18 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +17 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProjectHelper.cs +96 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +5 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +87 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +2 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs +45 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs +35 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +16 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Proj.cs +6 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +143 -36
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +184 -48
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +5 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +32 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/MiscellaneousTests.cs +85 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +402 -102
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +342 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatedDependencyListTests.cs +60 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryDirectory.cs +18 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestLogger.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/BindingRedirectsTests.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackagesConfigUpdaterTests.cs +24 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +4 -14
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs +84 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs +66 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +95 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +1 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/AssertEx.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/LinuxOnlyAttribute.cs +12 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +558 -711
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/PathHelperTests.cs +47 -2
- data/lib/dependabot/nuget/analysis/analysis_json_reader.rb +4 -2
- data/lib/dependabot/nuget/analysis/dependency_analysis.rb +3 -3
- data/lib/dependabot/nuget/discovery/dependency_details.rb +10 -3
- data/lib/dependabot/nuget/discovery/dependency_file_discovery.rb +8 -12
- data/lib/dependabot/nuget/discovery/discovery_json_reader.rb +214 -29
- data/lib/dependabot/nuget/discovery/project_discovery.rb +41 -8
- data/lib/dependabot/nuget/discovery/workspace_discovery.rb +14 -19
- data/lib/dependabot/nuget/file_fetcher.rb +11 -393
- data/lib/dependabot/nuget/file_parser.rb +23 -61
- data/lib/dependabot/nuget/file_updater.rb +28 -23
- data/lib/dependabot/nuget/native_helpers.rb +14 -5
- data/lib/dependabot/nuget/update_checker/requirements_updater.rb +23 -27
- data/lib/dependabot/nuget/update_checker.rb +116 -190
- metadata +20 -32
- data/helpers/lib/NuGetUpdater/NuGetProjects/Directory.Packages.props +0 -29
- data/lib/dependabot/nuget/discovery/directory_packages_props_discovery.rb +0 -43
- data/lib/dependabot/nuget/file_fetcher/import_paths_finder.rb +0 -73
- data/lib/dependabot/nuget/file_fetcher/sln_project_paths_finder.rb +0 -60
- data/lib/dependabot/nuget/http_response_helpers.rb +0 -19
- data/lib/dependabot/nuget/native_discovery/native_dependency_details.rb +0 -102
- data/lib/dependabot/nuget/native_discovery/native_dependency_file_discovery.rb +0 -129
- data/lib/dependabot/nuget/native_discovery/native_discovery_json_reader.rb +0 -171
- data/lib/dependabot/nuget/native_discovery/native_evaluation_details.rb +0 -63
- data/lib/dependabot/nuget/native_discovery/native_project_discovery.rb +0 -82
- data/lib/dependabot/nuget/native_discovery/native_property_details.rb +0 -43
- data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +0 -68
- data/lib/dependabot/nuget/native_update_checker/native_requirements_updater.rb +0 -105
- data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +0 -201
- data/lib/dependabot/nuget/nuget_client.rb +0 -223
- data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +0 -116
- data/lib/dependabot/nuget/update_checker/dependency_finder.rb +0 -297
- data/lib/dependabot/nuget/update_checker/nupkg_fetcher.rb +0 -221
- data/lib/dependabot/nuget/update_checker/nuspec_fetcher.rb +0 -110
- data/lib/dependabot/nuget/update_checker/property_updater.rb +0 -196
- data/lib/dependabot/nuget/update_checker/repository_finder.rb +0 -466
- data/lib/dependabot/nuget/update_checker/tfm_comparer.rb +0 -34
- data/lib/dependabot/nuget/update_checker/tfm_finder.rb +0 -30
- data/lib/dependabot/nuget/update_checker/version_finder.rb +0 -449
@@ -1,201 +0,0 @@
|
|
1
|
-
# typed: strong
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "dependabot/nuget/analysis/analysis_json_reader"
|
5
|
-
require "dependabot/nuget/native_discovery/native_discovery_json_reader"
|
6
|
-
require "dependabot/update_checkers"
|
7
|
-
require "dependabot/update_checkers/base"
|
8
|
-
require "sorbet-runtime"
|
9
|
-
|
10
|
-
module Dependabot
|
11
|
-
module Nuget
|
12
|
-
class NativeUpdateChecker < Dependabot::UpdateCheckers::Base
|
13
|
-
extend T::Sig
|
14
|
-
|
15
|
-
require_relative "native_requirements_updater"
|
16
|
-
|
17
|
-
sig { override.returns(T.nilable(String)) }
|
18
|
-
def latest_version
|
19
|
-
# No need to find latest version for transitive dependencies unless they have a vulnerability.
|
20
|
-
return dependency.version if !dependency.top_level? && !vulnerable?
|
21
|
-
|
22
|
-
# if no update sources have the requisite package, then we can only assume that the current version is correct
|
23
|
-
@latest_version = T.let(
|
24
|
-
update_analysis.dependency_analysis.updated_version,
|
25
|
-
T.nilable(String)
|
26
|
-
)
|
27
|
-
end
|
28
|
-
|
29
|
-
sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
|
30
|
-
def latest_resolvable_version
|
31
|
-
# We always want a full unlock since any package update could update peer dependencies as well.
|
32
|
-
# To force a full unlock instead of an own unlock, we return nil.
|
33
|
-
nil
|
34
|
-
end
|
35
|
-
|
36
|
-
sig { override.returns(Dependabot::Nuget::Version) }
|
37
|
-
def lowest_security_fix_version
|
38
|
-
update_analysis.dependency_analysis.numeric_updated_version
|
39
|
-
end
|
40
|
-
|
41
|
-
sig { override.returns(T.nilable(Dependabot::Nuget::Version)) }
|
42
|
-
def lowest_resolvable_security_fix_version
|
43
|
-
return nil if version_comes_from_multi_dependency_property?
|
44
|
-
|
45
|
-
update_analysis.dependency_analysis.numeric_updated_version
|
46
|
-
end
|
47
|
-
|
48
|
-
sig { override.returns(NilClass) }
|
49
|
-
def latest_resolvable_version_with_no_unlock
|
50
|
-
# Irrelevant, since Nuget has a single dependency file
|
51
|
-
nil
|
52
|
-
end
|
53
|
-
|
54
|
-
sig { override.returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
55
|
-
def updated_requirements
|
56
|
-
dep_details = updated_dependency_details.find { |d| d.name.casecmp?(dependency.name) }
|
57
|
-
NativeRequirementsUpdater.new(
|
58
|
-
requirements: dependency.requirements,
|
59
|
-
dependency_details: dep_details
|
60
|
-
).updated_requirements
|
61
|
-
end
|
62
|
-
|
63
|
-
sig { returns(T::Boolean) }
|
64
|
-
def up_to_date?
|
65
|
-
!update_analysis.dependency_analysis.can_update
|
66
|
-
end
|
67
|
-
|
68
|
-
sig { returns(T::Boolean) }
|
69
|
-
def requirements_unlocked_or_can_be?
|
70
|
-
update_analysis.dependency_analysis.can_update
|
71
|
-
end
|
72
|
-
|
73
|
-
sig { returns(T::Boolean) }
|
74
|
-
def public_latest_version_resolvable_with_full_unlock?
|
75
|
-
latest_version_resolvable_with_full_unlock?
|
76
|
-
end
|
77
|
-
|
78
|
-
sig { returns(T::Array[Dependabot::Dependency]) }
|
79
|
-
def public_updated_dependencies_after_full_unlock
|
80
|
-
updated_dependencies_after_full_unlock
|
81
|
-
end
|
82
|
-
|
83
|
-
private
|
84
|
-
|
85
|
-
sig { returns(AnalysisJsonReader) }
|
86
|
-
def update_analysis
|
87
|
-
@update_analysis ||= T.let(request_analysis, T.nilable(AnalysisJsonReader))
|
88
|
-
end
|
89
|
-
|
90
|
-
sig { returns(String) }
|
91
|
-
def dependency_file_path
|
92
|
-
File.join(NativeDiscoveryJsonReader.temp_directory, "dependency", "#{dependency.name}.json")
|
93
|
-
end
|
94
|
-
|
95
|
-
sig { returns(AnalysisJsonReader) }
|
96
|
-
def request_analysis
|
97
|
-
discovery_file_path = NativeDiscoveryJsonReader.get_discovery_file_path_from_dependency_files(dependency_files)
|
98
|
-
analysis_folder_path = AnalysisJsonReader.temp_directory
|
99
|
-
|
100
|
-
write_dependency_info
|
101
|
-
|
102
|
-
NativeHelpers.run_nuget_analyze_tool(repo_root: T.must(repo_contents_path),
|
103
|
-
discovery_file_path: discovery_file_path,
|
104
|
-
dependency_file_path: dependency_file_path,
|
105
|
-
analysis_folder_path: analysis_folder_path,
|
106
|
-
credentials: credentials)
|
107
|
-
|
108
|
-
analysis_json = AnalysisJsonReader.analysis_json(dependency_name: dependency.name)
|
109
|
-
|
110
|
-
AnalysisJsonReader.new(analysis_json: T.must(analysis_json))
|
111
|
-
end
|
112
|
-
|
113
|
-
sig { void }
|
114
|
-
def write_dependency_info
|
115
|
-
dependency_info = {
|
116
|
-
Name: dependency.name,
|
117
|
-
Version: dependency.version.to_s,
|
118
|
-
IsVulnerable: vulnerable?,
|
119
|
-
IgnoredVersions: ignored_versions,
|
120
|
-
Vulnerabilities: security_advisories.map do |vulnerability|
|
121
|
-
{
|
122
|
-
DependencyName: vulnerability.dependency_name,
|
123
|
-
PackageManager: vulnerability.package_manager,
|
124
|
-
VulnerableVersions: vulnerability.vulnerable_versions.map(&:to_s),
|
125
|
-
SafeVersions: vulnerability.safe_versions.map(&:to_s)
|
126
|
-
}
|
127
|
-
end
|
128
|
-
}.to_json
|
129
|
-
dependency_directory = File.dirname(dependency_file_path)
|
130
|
-
|
131
|
-
begin
|
132
|
-
Dir.mkdir(dependency_directory)
|
133
|
-
rescue StandardError
|
134
|
-
nil?
|
135
|
-
end
|
136
|
-
|
137
|
-
Dependabot.logger.info("Writing dependency info: #{dependency_info}")
|
138
|
-
File.write(dependency_file_path, dependency_info)
|
139
|
-
end
|
140
|
-
|
141
|
-
sig { returns(Dependabot::FileParsers::Base::DependencySet) }
|
142
|
-
def discovered_dependencies
|
143
|
-
discovery_json_reader = NativeDiscoveryJsonReader.get_discovery_from_dependency_files(dependency_files)
|
144
|
-
discovery_json_reader.dependency_set
|
145
|
-
end
|
146
|
-
|
147
|
-
sig { override.returns(T::Boolean) }
|
148
|
-
def latest_version_resolvable_with_full_unlock?
|
149
|
-
# We always want a full unlock since any package update could update peer dependencies as well.
|
150
|
-
true
|
151
|
-
end
|
152
|
-
|
153
|
-
sig { override.returns(T::Array[Dependabot::Dependency]) }
|
154
|
-
def updated_dependencies_after_full_unlock
|
155
|
-
dependencies = discovered_dependencies.dependencies
|
156
|
-
updated_dependency_details.filter_map do |dependency_details|
|
157
|
-
dep = dependencies.find { |d| d.name.casecmp(dependency_details.name)&.zero? }
|
158
|
-
next unless dep
|
159
|
-
|
160
|
-
metadata = {}
|
161
|
-
# For peer dependencies, instruct updater to not directly update this dependency
|
162
|
-
metadata = { information_only: true } unless dependency.name.casecmp(dependency_details.name)&.zero?
|
163
|
-
|
164
|
-
# rebuild the new requirements with the updated dependency details
|
165
|
-
updated_reqs = dep.requirements.map do |r|
|
166
|
-
r = r.clone
|
167
|
-
r[:requirement] = dependency_details.version
|
168
|
-
r[:source] = {
|
169
|
-
type: "nuget_repo",
|
170
|
-
source_url: dependency_details.info_url
|
171
|
-
}
|
172
|
-
r
|
173
|
-
end
|
174
|
-
|
175
|
-
Dependency.new(
|
176
|
-
name: dep.name,
|
177
|
-
version: dependency_details.version,
|
178
|
-
requirements: updated_reqs,
|
179
|
-
previous_version: dep.version,
|
180
|
-
previous_requirements: dep.requirements,
|
181
|
-
package_manager: dep.package_manager,
|
182
|
-
metadata: metadata
|
183
|
-
)
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
sig { returns(T::Array[Dependabot::Nuget::NativeDependencyDetails]) }
|
188
|
-
def updated_dependency_details
|
189
|
-
@updated_dependency_details ||= T.let(update_analysis.dependency_analysis.updated_dependencies,
|
190
|
-
T.nilable(T::Array[Dependabot::Nuget::NativeDependencyDetails]))
|
191
|
-
end
|
192
|
-
|
193
|
-
sig { returns(T::Boolean) }
|
194
|
-
def version_comes_from_multi_dependency_property?
|
195
|
-
update_analysis.dependency_analysis.version_comes_from_multi_dependency_property
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
Dependabot::UpdateCheckers.register("nuget", Dependabot::Nuget::UpdateChecker)
|
@@ -1,223 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "dependabot/nuget/cache_manager"
|
5
|
-
require "dependabot/nuget/http_response_helpers"
|
6
|
-
require "dependabot/nuget/update_checker/repository_finder"
|
7
|
-
require "sorbet-runtime"
|
8
|
-
|
9
|
-
module Dependabot
|
10
|
-
module Nuget
|
11
|
-
class NugetClient
|
12
|
-
extend T::Sig
|
13
|
-
|
14
|
-
sig do
|
15
|
-
params(dependency_name: String, repository_details: T::Hash[Symbol, String])
|
16
|
-
.returns(T.nilable(T::Set[String]))
|
17
|
-
end
|
18
|
-
def self.get_package_versions(dependency_name, repository_details)
|
19
|
-
repository_type = repository_details.fetch(:repository_type)
|
20
|
-
if repository_type == "v3"
|
21
|
-
get_package_versions_v3(dependency_name, repository_details)
|
22
|
-
elsif repository_type == "v2"
|
23
|
-
get_package_versions_v2(dependency_name, repository_details)
|
24
|
-
elsif repository_type == "local"
|
25
|
-
get_package_versions_local(dependency_name, repository_details)
|
26
|
-
else
|
27
|
-
raise "Unknown repository type: #{repository_type}"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
sig do
|
32
|
-
params(dependency_name: String, repository_details: T::Hash[Symbol, String])
|
33
|
-
.returns(T.nilable(T::Set[String]))
|
34
|
-
end
|
35
|
-
private_class_method def self.get_package_versions_local(dependency_name, repository_details)
|
36
|
-
url = repository_details.fetch(:base_url)
|
37
|
-
raise "Local repo #{url} doesn't exist or isn't a directory" unless File.exist?(url) && File.directory?(url)
|
38
|
-
|
39
|
-
package_dir = File.join(url, dependency_name)
|
40
|
-
|
41
|
-
versions = Set.new
|
42
|
-
return versions unless File.exist?(package_dir) && File.directory?(package_dir)
|
43
|
-
|
44
|
-
Dir.each_child(package_dir) do |child|
|
45
|
-
versions.add(child) if File.directory?(File.join(package_dir, child))
|
46
|
-
end
|
47
|
-
|
48
|
-
versions
|
49
|
-
end
|
50
|
-
|
51
|
-
sig do
|
52
|
-
params(dependency_name: String, repository_details: T::Hash[Symbol, String])
|
53
|
-
.returns(T.nilable(T::Set[String]))
|
54
|
-
end
|
55
|
-
private_class_method def self.get_package_versions_v3(dependency_name, repository_details)
|
56
|
-
# Use the registration URL if possible because it is fast and correct
|
57
|
-
if repository_details[:registration_url]
|
58
|
-
get_versions_from_registration_v3(repository_details)
|
59
|
-
# use the search API if not because it is slow but correct
|
60
|
-
elsif repository_details[:search_url]
|
61
|
-
get_versions_from_search_url_v3(repository_details, dependency_name)
|
62
|
-
# Otherwise, use the versions URL (fast but wrong because it includes unlisted versions)
|
63
|
-
elsif repository_details[:versions_url]
|
64
|
-
get_versions_from_versions_url_v3(repository_details)
|
65
|
-
else
|
66
|
-
raise "No version sources were available for #{dependency_name} in #{repository_details}"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
sig do
|
71
|
-
params(dependency_name: String, repository_details: T::Hash[Symbol, String])
|
72
|
-
.returns(T.nilable(T::Set[String]))
|
73
|
-
end
|
74
|
-
private_class_method def self.get_package_versions_v2(dependency_name, repository_details)
|
75
|
-
doc = execute_xml_nuget_request(repository_details.fetch(:versions_url), repository_details)
|
76
|
-
return unless doc
|
77
|
-
|
78
|
-
# v2 APIs can differ, but all tested have this title value set to the name of the package
|
79
|
-
title_nodes = doc.xpath("/feed/entry/title")
|
80
|
-
matching_versions = Set.new
|
81
|
-
title_nodes.each do |title_node|
|
82
|
-
return nil unless title_node.text
|
83
|
-
|
84
|
-
next unless title_node.text.casecmp?(dependency_name)
|
85
|
-
|
86
|
-
version_node = title_node.parent.xpath("properties/Version")
|
87
|
-
matching_versions << version_node.text if version_node && version_node.text
|
88
|
-
end
|
89
|
-
|
90
|
-
matching_versions
|
91
|
-
end
|
92
|
-
|
93
|
-
sig { params(repository_details: T::Hash[Symbol, String]).returns(T.nilable(T::Set[String])) }
|
94
|
-
private_class_method def self.get_versions_from_versions_url_v3(repository_details)
|
95
|
-
body = execute_json_nuget_request(repository_details.fetch(:versions_url), repository_details)
|
96
|
-
ver_array = T.let(body&.fetch("versions"), T.nilable(T::Array[String]))
|
97
|
-
ver_array&.to_set
|
98
|
-
end
|
99
|
-
|
100
|
-
sig { params(repository_details: T::Hash[Symbol, String]).returns(T.nilable(T::Set[String])) }
|
101
|
-
private_class_method def self.get_versions_from_registration_v3(repository_details)
|
102
|
-
url = repository_details.fetch(:registration_url)
|
103
|
-
body = execute_json_nuget_request(url, repository_details)
|
104
|
-
|
105
|
-
return unless body
|
106
|
-
|
107
|
-
pages = body.fetch("items")
|
108
|
-
versions = T.let(Set.new, T::Set[String])
|
109
|
-
pages.each do |page|
|
110
|
-
items = page["items"]
|
111
|
-
if items
|
112
|
-
# inlined entries
|
113
|
-
get_versions_from_inline_page(items, versions)
|
114
|
-
else
|
115
|
-
# paged entries
|
116
|
-
page_url = page["@id"]
|
117
|
-
page_body = execute_json_nuget_request(page_url, repository_details)
|
118
|
-
next unless page_body
|
119
|
-
|
120
|
-
items = page_body.fetch("items")
|
121
|
-
items.each do |item|
|
122
|
-
catalog_entry = item.fetch("catalogEntry")
|
123
|
-
versions << catalog_entry.fetch("version") if catalog_entry["listed"] == true
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
versions
|
129
|
-
end
|
130
|
-
|
131
|
-
sig { params(items: T::Array[T::Hash[String, T.untyped]], versions: T::Set[String]).void }
|
132
|
-
private_class_method def self.get_versions_from_inline_page(items, versions)
|
133
|
-
items.each do |item|
|
134
|
-
catalog_entry = item["catalogEntry"]
|
135
|
-
|
136
|
-
# a package is considered listed if the `listed` property is either `true` or missing
|
137
|
-
listed_property = catalog_entry["listed"]
|
138
|
-
is_listed = listed_property.nil? || listed_property == true
|
139
|
-
if is_listed
|
140
|
-
vers = catalog_entry["version"]
|
141
|
-
versions << vers
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
sig do
|
147
|
-
params(repository_details: T::Hash[Symbol, String], dependency_name: String)
|
148
|
-
.returns(T.nilable(T::Set[String]))
|
149
|
-
end
|
150
|
-
private_class_method def self.get_versions_from_search_url_v3(repository_details, dependency_name)
|
151
|
-
search_url = repository_details.fetch(:search_url)
|
152
|
-
body = execute_json_nuget_request(search_url, repository_details)
|
153
|
-
|
154
|
-
body&.fetch("data")
|
155
|
-
&.find { |d| d.fetch("id").casecmp(dependency_name.downcase).zero? }
|
156
|
-
&.fetch("versions")
|
157
|
-
&.map { |d| d.fetch("version") }
|
158
|
-
&.to_set
|
159
|
-
end
|
160
|
-
|
161
|
-
sig do
|
162
|
-
params(url: String, repository_details: T::Hash[Symbol, T.untyped]).returns(T.nilable(Nokogiri::XML::Document))
|
163
|
-
end
|
164
|
-
private_class_method def self.execute_xml_nuget_request(url, repository_details)
|
165
|
-
response = execute_nuget_request_internal(
|
166
|
-
url: url,
|
167
|
-
auth_header: repository_details.fetch(:auth_header),
|
168
|
-
repository_url: repository_details.fetch(:repository_url)
|
169
|
-
)
|
170
|
-
return unless response.status == 200
|
171
|
-
|
172
|
-
doc = Nokogiri::XML(response.body)
|
173
|
-
doc.remove_namespaces!
|
174
|
-
doc
|
175
|
-
end
|
176
|
-
|
177
|
-
sig do
|
178
|
-
params(url: String,
|
179
|
-
repository_details: T::Hash[Symbol, T.untyped])
|
180
|
-
.returns(T.nilable(T::Hash[T.untyped, T.untyped]))
|
181
|
-
end
|
182
|
-
private_class_method def self.execute_json_nuget_request(url, repository_details)
|
183
|
-
response = execute_nuget_request_internal(
|
184
|
-
url: url,
|
185
|
-
auth_header: repository_details.fetch(:auth_header),
|
186
|
-
repository_url: repository_details.fetch(:repository_url)
|
187
|
-
)
|
188
|
-
return unless response.status == 200
|
189
|
-
|
190
|
-
body = HttpResponseHelpers.remove_wrapping_zero_width_chars(response.body)
|
191
|
-
JSON.parse(body)
|
192
|
-
end
|
193
|
-
|
194
|
-
sig do
|
195
|
-
params(url: String, auth_header: T::Hash[Symbol, T.untyped], repository_url: String).returns(Excon::Response)
|
196
|
-
end
|
197
|
-
private_class_method def self.execute_nuget_request_internal(url:, auth_header:, repository_url:)
|
198
|
-
cache = CacheManager.cache("dependency_url_search_cache")
|
199
|
-
if cache[url].nil?
|
200
|
-
response = Dependabot::RegistryClient.get(
|
201
|
-
url: url,
|
202
|
-
headers: auth_header
|
203
|
-
)
|
204
|
-
|
205
|
-
if [401, 402, 403].include?(response.status)
|
206
|
-
raise Dependabot::PrivateSourceAuthenticationFailure, repository_url
|
207
|
-
end
|
208
|
-
|
209
|
-
cache[url] = response if !CacheManager.caching_disabled? && response.status == 200
|
210
|
-
else
|
211
|
-
response = cache[url]
|
212
|
-
end
|
213
|
-
|
214
|
-
response
|
215
|
-
rescue Excon::Error::Timeout, Excon::Error::Socket
|
216
|
-
repo_url = repository_url
|
217
|
-
raise if repo_url == Dependabot::Nuget::RepositoryFinder::DEFAULT_REPOSITORY_URL
|
218
|
-
|
219
|
-
raise PrivateSourceTimedOut, repo_url
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
@@ -1,116 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "sorbet-runtime"
|
5
|
-
|
6
|
-
require "dependabot/update_checkers/base"
|
7
|
-
|
8
|
-
module Dependabot
|
9
|
-
module Nuget
|
10
|
-
class CompatibilityChecker
|
11
|
-
extend T::Sig
|
12
|
-
|
13
|
-
require_relative "nuspec_fetcher"
|
14
|
-
require_relative "nupkg_fetcher"
|
15
|
-
require_relative "tfm_finder"
|
16
|
-
require_relative "tfm_comparer"
|
17
|
-
|
18
|
-
sig do
|
19
|
-
params(
|
20
|
-
dependency_urls: T::Array[T::Hash[Symbol, String]],
|
21
|
-
dependency: Dependabot::Dependency
|
22
|
-
).void
|
23
|
-
end
|
24
|
-
def initialize(dependency_urls:, dependency:)
|
25
|
-
@dependency_urls = dependency_urls
|
26
|
-
@dependency = dependency
|
27
|
-
end
|
28
|
-
|
29
|
-
sig { params(version: String).returns(T::Boolean) }
|
30
|
-
def compatible?(version)
|
31
|
-
nuspec_xml = NuspecFetcher.fetch_nuspec(dependency_urls, dependency.name, version)
|
32
|
-
return false unless nuspec_xml
|
33
|
-
|
34
|
-
# development dependencies are packages such as analyzers which need to be compatible with the compiler not the
|
35
|
-
# project itself, but some packages that report themselves as development dependencies still contain target
|
36
|
-
# framework dependencies and should be checked for compatibility through the regular means
|
37
|
-
return true if pure_development_dependency?(nuspec_xml)
|
38
|
-
|
39
|
-
package_tfms = parse_package_tfms(nuspec_xml)
|
40
|
-
package_tfms = fetch_package_tfms(version) if package_tfms.empty?
|
41
|
-
# nil is a special return value that indicates that the package is likely a development dependency
|
42
|
-
return true if package_tfms.nil?
|
43
|
-
return false if package_tfms.empty?
|
44
|
-
|
45
|
-
return false if project_tfms.nil? || project_tfms&.empty?
|
46
|
-
|
47
|
-
TfmComparer.are_frameworks_compatible?(T.must(project_tfms), package_tfms)
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
sig { returns(T::Array[T::Hash[Symbol, String]]) }
|
53
|
-
attr_reader :dependency_urls
|
54
|
-
|
55
|
-
sig { returns(Dependabot::Dependency) }
|
56
|
-
attr_reader :dependency
|
57
|
-
|
58
|
-
sig { params(nuspec_xml: Nokogiri::XML::Document).returns(T::Boolean) }
|
59
|
-
def pure_development_dependency?(nuspec_xml)
|
60
|
-
contents = nuspec_xml.at_xpath("package/metadata/developmentDependency")&.content&.strip
|
61
|
-
return false unless contents # no `developmentDependency` element
|
62
|
-
|
63
|
-
self_reports_as_development_dependency = contents.casecmp?("true")
|
64
|
-
return false unless self_reports_as_development_dependency
|
65
|
-
|
66
|
-
# even though a package self-reports as a development dependency, it might not be if it has dependency groups
|
67
|
-
# with a target framework
|
68
|
-
dependency_groups_with_target_framework =
|
69
|
-
nuspec_xml.at_xpath("/package/metadata/dependencies/group[@targetFramework]")
|
70
|
-
dependency_groups_with_target_framework.to_a.empty?
|
71
|
-
end
|
72
|
-
|
73
|
-
sig { params(nuspec_xml: Nokogiri::XML::Document).returns(T::Array[String]) }
|
74
|
-
def parse_package_tfms(nuspec_xml)
|
75
|
-
nuspec_xml.xpath("//dependencies/group").filter_map { |group| group.attribute("targetFramework") }
|
76
|
-
end
|
77
|
-
|
78
|
-
sig { returns(T.nilable(T::Array[String])) }
|
79
|
-
def project_tfms
|
80
|
-
@project_tfms ||= T.let(TfmFinder.frameworks(dependency), T.nilable(T::Array[String]))
|
81
|
-
end
|
82
|
-
|
83
|
-
sig { params(dependency_version: String).returns(T.nilable(T::Array[String])) }
|
84
|
-
def fetch_package_tfms(dependency_version)
|
85
|
-
cache = CacheManager.cache("compatibility_checker_tfms_cache")
|
86
|
-
key = "#{dependency.name}::#{dependency_version}"
|
87
|
-
|
88
|
-
cache[key] ||= begin
|
89
|
-
nupkg_buffer = NupkgFetcher.fetch_nupkg_buffer(dependency_urls, dependency.name, dependency_version)
|
90
|
-
return [] unless nupkg_buffer
|
91
|
-
|
92
|
-
# Parse tfms from the folders beneath the lib folder
|
93
|
-
folder_name = "lib/"
|
94
|
-
tfms = Set.new
|
95
|
-
Zip::File.open_buffer(nupkg_buffer) do |zip|
|
96
|
-
lib_file_entries = zip.select { |entry| entry.name.start_with?(folder_name) }
|
97
|
-
# If there is no lib folder in this package, assume it is a development dependency
|
98
|
-
return nil if lib_file_entries.empty?
|
99
|
-
|
100
|
-
lib_file_entries.each do |entry|
|
101
|
-
_, tfm = entry.name.split("/").first(2)
|
102
|
-
|
103
|
-
# some zip compressors create empty directory entries (in this case `lib/`) which can cause the string
|
104
|
-
# split to return `nil`, so we have to explicitly guard against that
|
105
|
-
tfms << tfm if tfm
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
tfms.to_a
|
110
|
-
end
|
111
|
-
|
112
|
-
cache[key]
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|