dependabot-nuget 0.248.0 → 0.250.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/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +57 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +26 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +31 -0
- data/lib/dependabot/nuget/file_fetcher/import_paths_finder.rb +1 -0
- data/lib/dependabot/nuget/file_fetcher/sln_project_paths_finder.rb +2 -0
- data/lib/dependabot/nuget/file_parser/dotnet_tools_json_parser.rb +1 -0
- data/lib/dependabot/nuget/file_parser/global_json_parser.rb +1 -0
- data/lib/dependabot/nuget/file_parser/packages_config_parser.rb +1 -0
- data/lib/dependabot/nuget/file_parser/project_file_parser.rb +1 -0
- data/lib/dependabot/nuget/file_parser/property_value_finder.rb +2 -0
- data/lib/dependabot/nuget/file_parser.rb +32 -11
- data/lib/dependabot/nuget/file_updater/property_value_updater.rb +1 -0
- data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +28 -7
- data/lib/dependabot/nuget/update_checker/dependency_finder.rb +70 -19
- data/lib/dependabot/nuget/update_checker/nuspec_fetcher.rb +1 -1
- data/lib/dependabot/nuget/update_checker/property_updater.rb +108 -44
- data/lib/dependabot/nuget/update_checker/repository_finder.rb +90 -18
- data/lib/dependabot/nuget/update_checker/tfm_comparer.rb +8 -3
- data/lib/dependabot/nuget/update_checker/tfm_finder.rb +51 -13
- metadata +5 -5
@@ -1,6 +1,8 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
4
6
|
require "dependabot/update_checkers/base"
|
5
7
|
require "dependabot/nuget/file_parser"
|
6
8
|
|
@@ -8,28 +10,47 @@ module Dependabot
|
|
8
10
|
module Nuget
|
9
11
|
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
10
12
|
class PropertyUpdater
|
13
|
+
extend T::Sig
|
14
|
+
|
11
15
|
require_relative "version_finder"
|
12
16
|
require_relative "requirements_updater"
|
13
17
|
require_relative "dependency_finder"
|
14
18
|
|
19
|
+
sig do
|
20
|
+
params(
|
21
|
+
dependency: Dependabot::Dependency,
|
22
|
+
dependency_files: T::Array[Dependabot::DependencyFile],
|
23
|
+
credentials: T::Array[Dependabot::Credential],
|
24
|
+
target_version_details: T.nilable(T::Hash[Symbol, String]),
|
25
|
+
ignored_versions: T::Array[String],
|
26
|
+
repo_contents_path: T.nilable(String),
|
27
|
+
raise_on_ignored: T::Boolean
|
28
|
+
).void
|
29
|
+
end
|
15
30
|
def initialize(dependency:, dependency_files:, credentials:,
|
16
31
|
target_version_details:, ignored_versions:,
|
17
|
-
raise_on_ignored: false
|
32
|
+
repo_contents_path:, raise_on_ignored: false)
|
18
33
|
@dependency = dependency
|
19
34
|
@dependency_files = dependency_files
|
20
35
|
@credentials = credentials
|
21
36
|
@ignored_versions = ignored_versions
|
22
37
|
@raise_on_ignored = raise_on_ignored
|
23
|
-
@target_version =
|
24
|
-
|
25
|
-
|
38
|
+
@target_version = T.let(
|
39
|
+
target_version_details&.fetch(:version),
|
40
|
+
T.nilable(T.any(String, Dependabot::Nuget::Version))
|
41
|
+
)
|
42
|
+
@source_details = T.let(
|
43
|
+
target_version_details&.slice(:nuspec_url, :repo_url, :source_url),
|
44
|
+
T.nilable(T::Hash[Symbol, String])
|
45
|
+
)
|
26
46
|
@repo_contents_path = repo_contents_path
|
27
47
|
end
|
28
48
|
|
49
|
+
sig { returns(T::Boolean) }
|
29
50
|
def update_possible?
|
30
51
|
return false unless target_version
|
31
52
|
|
32
|
-
@update_possible ||=
|
53
|
+
@update_possible ||= T.let(
|
33
54
|
dependencies_using_property.all? do |dep|
|
34
55
|
versions = VersionFinder.new(
|
35
56
|
dependency: dep,
|
@@ -42,42 +63,73 @@ module Dependabot
|
|
42
63
|
).versions.map { |v| v.fetch(:version) }
|
43
64
|
|
44
65
|
versions.include?(target_version) || versions.none?
|
45
|
-
end
|
66
|
+
end,
|
67
|
+
T.nilable(T::Boolean)
|
68
|
+
)
|
46
69
|
end
|
47
70
|
|
71
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
48
72
|
def updated_dependencies
|
49
73
|
raise "Update not possible!" unless update_possible?
|
50
74
|
|
51
|
-
@updated_dependencies ||=
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
75
|
+
@updated_dependencies ||= T.let(
|
76
|
+
begin
|
77
|
+
dependencies = T.let({}, T::Hash[String, Dependabot::Dependency])
|
78
|
+
|
79
|
+
dependencies_using_property.each do |dep|
|
80
|
+
# Only keep one copy of each dependency, the one with the highest target version.
|
81
|
+
visited_dependency = dependencies[dep.name.downcase]
|
82
|
+
next unless visited_dependency.nil? || T.must(visited_dependency.numeric_version) < target_version
|
83
|
+
|
84
|
+
updated_dependency = Dependency.new(
|
85
|
+
name: dep.name,
|
86
|
+
version: target_version.to_s,
|
87
|
+
requirements: updated_requirements(dep),
|
88
|
+
previous_version: dep.version,
|
89
|
+
previous_requirements: dep.requirements,
|
90
|
+
package_manager: dep.package_manager
|
91
|
+
)
|
92
|
+
dependencies[updated_dependency.name.downcase] = updated_dependency
|
93
|
+
# Add peer dependencies to the list of updated dependencies.
|
94
|
+
process_updated_peer_dependencies(updated_dependency, dependencies)
|
95
|
+
end
|
71
96
|
|
72
|
-
|
73
|
-
|
97
|
+
dependencies.map { |_, dependency| dependency }
|
98
|
+
end,
|
99
|
+
T.nilable(T::Array[Dependabot::Dependency])
|
100
|
+
)
|
74
101
|
end
|
75
102
|
|
76
103
|
private
|
77
104
|
|
78
|
-
|
79
|
-
|
105
|
+
sig { returns(Dependabot::Dependency) }
|
106
|
+
attr_reader :dependency
|
107
|
+
|
108
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
109
|
+
attr_reader :dependency_files
|
110
|
+
|
111
|
+
sig { returns(T.nilable(T.any(String, Dependabot::Nuget::Version))) }
|
112
|
+
attr_reader :target_version
|
80
113
|
|
114
|
+
sig { returns(T.nilable(T::Hash[Symbol, String])) }
|
115
|
+
attr_reader :source_details
|
116
|
+
|
117
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
118
|
+
attr_reader :credentials
|
119
|
+
|
120
|
+
sig { returns(T::Array[String]) }
|
121
|
+
attr_reader :ignored_versions
|
122
|
+
|
123
|
+
sig { returns(T.nilable(String)) }
|
124
|
+
attr_reader :repo_contents_path
|
125
|
+
|
126
|
+
sig do
|
127
|
+
params(
|
128
|
+
dependency: Dependabot::Dependency,
|
129
|
+
dependencies: T::Hash[String, Dependabot::Dependency]
|
130
|
+
)
|
131
|
+
.returns(T::Array[Dependabot::Dependency])
|
132
|
+
end
|
81
133
|
def process_updated_peer_dependencies(dependency, dependencies)
|
82
134
|
DependencyFinder.new(
|
83
135
|
dependency: dependency,
|
@@ -87,36 +139,48 @@ module Dependabot
|
|
87
139
|
).updated_peer_dependencies.each do |peer_dependency|
|
88
140
|
# Only keep one copy of each dependency, the one with the highest target version.
|
89
141
|
visited_dependency = dependencies[peer_dependency.name.downcase]
|
90
|
-
|
142
|
+
unless visited_dependency.nil? ||
|
143
|
+
T.must(visited_dependency.numeric_version) < peer_dependency.numeric_version
|
144
|
+
next
|
145
|
+
end
|
91
146
|
|
92
147
|
dependencies[peer_dependency.name.downcase] = peer_dependency
|
93
148
|
end
|
94
149
|
end
|
95
150
|
|
151
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
96
152
|
def dependencies_using_property
|
97
153
|
@dependencies_using_property ||=
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
154
|
+
T.let(
|
155
|
+
Nuget::FileParser.new(
|
156
|
+
dependency_files: dependency_files,
|
157
|
+
source: nil
|
158
|
+
).parse.select do |dep|
|
159
|
+
dep.requirements.any? do |r|
|
160
|
+
r.dig(:metadata, :property_name) == property_name
|
161
|
+
end
|
162
|
+
end,
|
163
|
+
T.nilable(T::Array[Dependabot::Dependency])
|
164
|
+
)
|
106
165
|
end
|
107
166
|
|
167
|
+
sig { returns(String) }
|
108
168
|
def property_name
|
109
|
-
@property_name ||=
|
110
|
-
|
111
|
-
|
169
|
+
@property_name ||= T.let(
|
170
|
+
dependency.requirements
|
171
|
+
.find { |r| r.dig(:metadata, :property_name) }
|
172
|
+
&.dig(:metadata, :property_name),
|
173
|
+
T.nilable(String)
|
174
|
+
)
|
112
175
|
|
113
176
|
raise "No requirement with a property name!" unless @property_name
|
114
177
|
|
115
178
|
@property_name
|
116
179
|
end
|
117
180
|
|
181
|
+
sig { params(dep: Dependabot::Dependency).returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
118
182
|
def updated_requirements(dep)
|
119
|
-
@updated_requirements ||= {}
|
183
|
+
@updated_requirements ||= T.let({}, T.nilable(T::Hash[String, T::Array[T::Hash[Symbol, T.untyped]]]))
|
120
184
|
@updated_requirements[dep.name] ||=
|
121
185
|
RequirementsUpdater.new(
|
122
186
|
requirements: dep.requirements,
|
@@ -1,8 +1,10 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "excon"
|
5
5
|
require "nokogiri"
|
6
|
+
require "sorbet-runtime"
|
7
|
+
|
6
8
|
require "dependabot/errors"
|
7
9
|
require "dependabot/update_checkers/base"
|
8
10
|
require "dependabot/registry_client"
|
@@ -12,23 +14,34 @@ require "dependabot/nuget/http_response_helpers"
|
|
12
14
|
module Dependabot
|
13
15
|
module Nuget
|
14
16
|
class RepositoryFinder
|
17
|
+
extend T::Sig
|
18
|
+
|
15
19
|
DEFAULT_REPOSITORY_URL = "https://api.nuget.org/v3/index.json"
|
16
20
|
DEFAULT_REPOSITORY_API_KEY = "nuget.org"
|
17
21
|
|
22
|
+
sig do
|
23
|
+
params(
|
24
|
+
dependency: Dependabot::Dependency,
|
25
|
+
credentials: T::Array[Dependabot::Credential],
|
26
|
+
config_files: T::Array[Dependabot::DependencyFile]
|
27
|
+
).void
|
28
|
+
end
|
18
29
|
def initialize(dependency:, credentials:, config_files: [])
|
19
30
|
@dependency = dependency
|
20
31
|
@credentials = credentials
|
21
32
|
@config_files = config_files
|
22
33
|
end
|
23
34
|
|
35
|
+
sig { returns(T::Array[T::Hash[Symbol, String]]) }
|
24
36
|
def dependency_urls
|
25
37
|
find_dependency_urls
|
26
38
|
end
|
27
39
|
|
40
|
+
sig { returns(T::Array[T::Hash[Symbol, String]]) }
|
28
41
|
def known_repositories
|
29
42
|
return @known_repositories if @known_repositories
|
30
43
|
|
31
|
-
@known_repositories
|
44
|
+
@known_repositories ||= T.let([], T.nilable(T::Array[T::Hash[Symbol, String]]))
|
32
45
|
@known_repositories += credential_repositories
|
33
46
|
@known_repositories += config_file_repositories
|
34
47
|
|
@@ -40,6 +53,7 @@ module Dependabot
|
|
40
53
|
@known_repositories.uniq
|
41
54
|
end
|
42
55
|
|
56
|
+
sig { params(dependency_name: String).returns(T::Hash[Symbol, T.untyped]) }
|
43
57
|
def self.get_default_repository_details(dependency_name)
|
44
58
|
{
|
45
59
|
base_url: "https://api.nuget.org/v3-flatcontainer/",
|
@@ -56,21 +70,33 @@ module Dependabot
|
|
56
70
|
|
57
71
|
private
|
58
72
|
|
59
|
-
|
73
|
+
sig { returns(Dependabot::Dependency) }
|
74
|
+
attr_reader :dependency
|
75
|
+
|
76
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
77
|
+
attr_reader :credentials
|
78
|
+
|
79
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
80
|
+
attr_reader :config_files
|
60
81
|
|
82
|
+
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
61
83
|
def find_dependency_urls
|
62
84
|
@find_dependency_urls ||=
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
85
|
+
T.let(
|
86
|
+
known_repositories.flat_map do |details|
|
87
|
+
if details.fetch(:url) == DEFAULT_REPOSITORY_URL
|
88
|
+
# Save a request for the default URL, since we already know how
|
89
|
+
# it addresses packages
|
90
|
+
next default_repository_details
|
91
|
+
end
|
69
92
|
|
70
|
-
|
71
|
-
|
93
|
+
build_url_for_details(details)
|
94
|
+
end.compact.uniq,
|
95
|
+
T.nilable(T::Array[T::Hash[Symbol, T.untyped]])
|
96
|
+
)
|
72
97
|
end
|
73
98
|
|
99
|
+
sig { params(repo_details: T::Hash[Symbol, T.untyped]).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
74
100
|
def build_url_for_details(repo_details)
|
75
101
|
url = repo_details.fetch(:url)
|
76
102
|
url_obj = URI.parse(url)
|
@@ -86,6 +112,7 @@ module Dependabot
|
|
86
112
|
details
|
87
113
|
end
|
88
114
|
|
115
|
+
sig { params(repo_details: T::Hash[Symbol, T.untyped]).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
89
116
|
def build_url_for_details_remote(repo_details)
|
90
117
|
response = get_repo_metadata(repo_details)
|
91
118
|
check_repo_response(response, repo_details)
|
@@ -118,11 +145,12 @@ module Dependabot
|
|
118
145
|
|
119
146
|
details
|
120
147
|
rescue JSON::ParserError
|
121
|
-
build_v2_url(response, repo_details)
|
148
|
+
build_v2_url(T.must(response), repo_details)
|
122
149
|
rescue Excon::Error::Timeout, Excon::Error::Socket
|
123
150
|
handle_timeout(repo_metadata_url: repo_details.fetch(:url))
|
124
151
|
end
|
125
152
|
|
153
|
+
sig { params(repo_details: T::Hash[Symbol, T.untyped]).returns(Excon::Response) }
|
126
154
|
def get_repo_metadata(repo_details)
|
127
155
|
url = repo_details.fetch(:url)
|
128
156
|
cache = CacheManager.cache("repo_finder_metadatacache")
|
@@ -138,6 +166,7 @@ module Dependabot
|
|
138
166
|
end
|
139
167
|
end
|
140
168
|
|
169
|
+
sig { params(metadata: T::Hash[String, T::Array[T::Hash[String, T.untyped]]]).returns(T.nilable(String)) }
|
141
170
|
def base_url_from_v3_metadata(metadata)
|
142
171
|
metadata
|
143
172
|
.fetch("resources", [])
|
@@ -145,6 +174,7 @@ module Dependabot
|
|
145
174
|
&.fetch("@id")
|
146
175
|
end
|
147
176
|
|
177
|
+
sig { params(metadata: T::Hash[String, T::Array[T::Hash[String, T.untyped]]]).returns(T.nilable(String)) }
|
148
178
|
def registration_url_from_v3_metadata(metadata)
|
149
179
|
allowed_registration_types = %w(
|
150
180
|
RegistrationsBaseUrl
|
@@ -159,6 +189,7 @@ module Dependabot
|
|
159
189
|
&.fetch("@id")
|
160
190
|
end
|
161
191
|
|
192
|
+
sig { params(metadata: T::Hash[String, T::Array[T::Hash[String, T.untyped]]]).returns(T.nilable(String)) }
|
162
193
|
def search_url_from_v3_metadata(metadata)
|
163
194
|
# allowable values from here: https://learn.microsoft.com/en-us/nuget/api/search-query-service-resource#versioning
|
164
195
|
allowed_search_types = %w(
|
@@ -173,6 +204,13 @@ module Dependabot
|
|
173
204
|
&.fetch("@id")
|
174
205
|
end
|
175
206
|
|
207
|
+
sig do
|
208
|
+
params(
|
209
|
+
response: Excon::Response,
|
210
|
+
repo_details: T::Hash[Symbol, T.untyped]
|
211
|
+
)
|
212
|
+
.returns(T::Hash[Symbol, T.untyped])
|
213
|
+
end
|
176
214
|
def build_v2_url(response, repo_details)
|
177
215
|
doc = Nokogiri::XML(response.body)
|
178
216
|
|
@@ -194,6 +232,7 @@ module Dependabot
|
|
194
232
|
}
|
195
233
|
end
|
196
234
|
|
235
|
+
sig { params(response: Excon::Response, details: T::Hash[Symbol, T.untyped]).void }
|
197
236
|
def check_repo_response(response, details)
|
198
237
|
return unless [401, 402, 403].include?(response.status)
|
199
238
|
raise if details.fetch(:url) == DEFAULT_REPOSITORY_URL
|
@@ -201,19 +240,25 @@ module Dependabot
|
|
201
240
|
raise PrivateSourceAuthenticationFailure, details.fetch(:url)
|
202
241
|
end
|
203
242
|
|
243
|
+
sig { params(repo_metadata_url: String).returns(T.noreturn) }
|
204
244
|
def handle_timeout(repo_metadata_url:)
|
205
245
|
raise if repo_metadata_url == DEFAULT_REPOSITORY_URL
|
206
246
|
|
207
247
|
raise PrivateSourceTimedOut, repo_metadata_url
|
208
248
|
end
|
209
249
|
|
250
|
+
sig { returns(T::Array[T::Hash[Symbol, String]]) }
|
210
251
|
def credential_repositories
|
211
252
|
@credential_repositories ||=
|
212
|
-
|
213
|
-
|
214
|
-
|
253
|
+
T.let(
|
254
|
+
credentials
|
255
|
+
.select { |cred| cred["type"] == "nuget_feed" && cred["url"] }
|
256
|
+
.map { |c| { url: c.fetch("url"), token: c["token"] } },
|
257
|
+
T.nilable(T::Array[T::Hash[Symbol, String]])
|
258
|
+
)
|
215
259
|
end
|
216
260
|
|
261
|
+
sig { returns(T::Array[T::Hash[Symbol, String]]) }
|
217
262
|
def config_file_repositories
|
218
263
|
config_files.flat_map { |file| repos_from_config_file(file) }
|
219
264
|
end
|
@@ -222,13 +267,14 @@ module Dependabot
|
|
222
267
|
# rubocop:disable Metrics/PerceivedComplexity
|
223
268
|
# rubocop:disable Metrics/MethodLength
|
224
269
|
# rubocop:disable Metrics/AbcSize
|
270
|
+
sig { params(config_file: Dependabot::DependencyFile).returns(T::Array[T::Hash[Symbol, String]]) }
|
225
271
|
def repos_from_config_file(config_file)
|
226
272
|
doc = Nokogiri::XML(config_file.content)
|
227
273
|
doc.remove_namespaces!
|
228
274
|
# analogous to having a root config with the default repository
|
229
275
|
base_sources = [{ url: DEFAULT_REPOSITORY_URL, key: "nuget.org" }]
|
230
276
|
|
231
|
-
sources = []
|
277
|
+
sources = T.let([], T::Array[T::Hash[Symbol, String]])
|
232
278
|
|
233
279
|
# regular package sources
|
234
280
|
doc.css("configuration > packageSources").children.each do |node|
|
@@ -269,6 +315,23 @@ module Dependabot
|
|
269
315
|
known_urls.include?(s.fetch(:url))
|
270
316
|
end
|
271
317
|
|
318
|
+
# filter out based on packageSourceMapping
|
319
|
+
package_mapping_elements = doc.xpath("/configuration/packageSourceMapping/packageSource/package[@pattern]")
|
320
|
+
matching_package_elements = package_mapping_elements.select do |package_element|
|
321
|
+
pattern = package_element.attribute("pattern").value
|
322
|
+
|
323
|
+
# reusing this function for a case insensitive GLOB pattern patch (e.g., "Microsoft.Azure.*")
|
324
|
+
File.fnmatch(pattern, @dependency.name, File::FNM_CASEFOLD)
|
325
|
+
end
|
326
|
+
longest_matching_package_element = matching_package_elements.max_by do |package_element|
|
327
|
+
package_element.attribute("pattern").value.length
|
328
|
+
end
|
329
|
+
matching_key = longest_matching_package_element&.parent&.attribute("key")&.value
|
330
|
+
if matching_key
|
331
|
+
# found a matching source, only keep that one
|
332
|
+
sources.select! { |s| s.fetch(:key) == matching_key }
|
333
|
+
end
|
334
|
+
|
272
335
|
add_config_file_credentials(sources: sources, doc: doc)
|
273
336
|
sources.each { |details| details.delete(:key) }
|
274
337
|
|
@@ -279,11 +342,13 @@ module Dependabot
|
|
279
342
|
# rubocop:enable Metrics/PerceivedComplexity
|
280
343
|
# rubocop:enable Metrics/CyclomaticComplexity
|
281
344
|
|
345
|
+
sig { returns(T::Hash[Symbol, T.untyped]) }
|
282
346
|
def default_repository_details
|
283
347
|
RepositoryFinder.get_default_repository_details(dependency.name)
|
284
348
|
end
|
285
349
|
|
286
350
|
# rubocop:disable Metrics/PerceivedComplexity
|
351
|
+
sig { params(doc: Nokogiri::XML::Document).returns(T::Array[String]) }
|
287
352
|
def disabled_sources(doc)
|
288
353
|
doc.css("configuration > disabledPackageSources > add").filter_map do |node|
|
289
354
|
value = node.attribute("value")&.value ||
|
@@ -298,6 +363,13 @@ module Dependabot
|
|
298
363
|
# rubocop:enable Metrics/PerceivedComplexity
|
299
364
|
|
300
365
|
# rubocop:disable Metrics/PerceivedComplexity
|
366
|
+
sig do
|
367
|
+
params(
|
368
|
+
sources: T::Array[T::Hash[Symbol, T.nilable(String)]],
|
369
|
+
doc: Nokogiri::XML::Document
|
370
|
+
)
|
371
|
+
.void
|
372
|
+
end
|
301
373
|
def add_config_file_credentials(sources:, doc:)
|
302
374
|
sources.each do |source_details|
|
303
375
|
key = source_details.fetch(:key)
|
@@ -329,11 +401,10 @@ module Dependabot
|
|
329
401
|
# Any non-ascii characters in the tag with cause a syntax error
|
330
402
|
next source_details[:token] = nil
|
331
403
|
end
|
332
|
-
|
333
|
-
sources
|
334
404
|
end
|
335
405
|
# rubocop:enable Metrics/PerceivedComplexity
|
336
406
|
|
407
|
+
sig { params(string: String).returns(String) }
|
337
408
|
def expand_windows_style_environment_variables(string)
|
338
409
|
# NuGet.Config files can have Windows-style environment variables that need to be replaced
|
339
410
|
# https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file#using-environment-variables
|
@@ -352,6 +423,7 @@ module Dependabot
|
|
352
423
|
end
|
353
424
|
end
|
354
425
|
|
426
|
+
sig { params(token: T.nilable(String)).returns(T::Hash[String, String]) }
|
355
427
|
def auth_header_for_token(token)
|
356
428
|
return {} unless token
|
357
429
|
|
@@ -1,6 +1,8 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strong
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
4
6
|
require "dependabot/update_checkers/base"
|
5
7
|
require "dependabot/nuget/version"
|
6
8
|
require "dependabot/nuget/requirement"
|
@@ -10,19 +12,22 @@ require "dependabot/shared_helpers"
|
|
10
12
|
module Dependabot
|
11
13
|
module Nuget
|
12
14
|
class TfmComparer
|
15
|
+
extend T::Sig
|
16
|
+
|
17
|
+
sig { params(project_tfms: T::Array[String], package_tfms: T::Array[String]).returns(T::Boolean) }
|
13
18
|
def self.are_frameworks_compatible?(project_tfms, package_tfms)
|
14
19
|
return false if package_tfms.empty?
|
15
20
|
return false if project_tfms.empty?
|
16
21
|
|
17
22
|
key = "project_ftms:#{project_tfms.sort.join(',')}:package_tfms:#{package_tfms.sort.join(',')}".downcase
|
18
23
|
|
19
|
-
@cached_framework_check ||= {}
|
24
|
+
@cached_framework_check ||= T.let({}, T.nilable(T::Hash[String, T::Boolean]))
|
20
25
|
unless @cached_framework_check.key?(key)
|
21
26
|
@cached_framework_check[key] =
|
22
27
|
NativeHelpers.run_nuget_framework_check(project_tfms,
|
23
28
|
package_tfms)
|
24
29
|
end
|
25
|
-
@cached_framework_check[key]
|
30
|
+
T.must(@cached_framework_check[key])
|
26
31
|
end
|
27
32
|
end
|
28
33
|
end
|