dependabot-nuget 0.288.0 → 0.290.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|