dependabot-nuget 0.247.0 → 0.249.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/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 +25 -5
- 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_fetcher.rb +12 -8
- 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 +42 -11
- data/lib/dependabot/nuget/file_updater/property_value_updater.rb +1 -0
- data/lib/dependabot/nuget/nuget_config_credential_helpers.rb +10 -1
- data/lib/dependabot/nuget/requirement.rb +17 -8
- 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/nupkg_fetcher.rb +76 -8
- data/lib/dependabot/nuget/update_checker/nuspec_fetcher.rb +25 -3
- 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/requirements_updater.rb +32 -9
- data/lib/dependabot/nuget/update_checker/tfm_comparer.rb +8 -3
- data/lib/dependabot/nuget/update_checker/tfm_finder.rb +51 -13
- data/lib/dependabot/nuget/update_checker/version_finder.rb +167 -62
- data/lib/dependabot/nuget/update_checker.rb +73 -29
- metadata +5 -5
@@ -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,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
#######################################################################
|
@@ -6,6 +6,8 @@
|
|
6
6
|
# https://docs.microsoft.com/en-us/nuget/reference/package-versioning #
|
7
7
|
#######################################################################
|
8
8
|
|
9
|
+
require "sorbet-runtime"
|
10
|
+
|
9
11
|
require "dependabot/update_checkers/base"
|
10
12
|
require "dependabot/nuget/version"
|
11
13
|
|
@@ -13,14 +15,25 @@ module Dependabot
|
|
13
15
|
module Nuget
|
14
16
|
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
15
17
|
class RequirementsUpdater
|
18
|
+
extend T::Sig
|
19
|
+
|
20
|
+
sig do
|
21
|
+
params(
|
22
|
+
requirements: T::Array[T::Hash[Symbol, T.untyped]],
|
23
|
+
latest_version: T.nilable(T.any(String, Dependabot::Nuget::Version)),
|
24
|
+
source_details: T.nilable(T::Hash[Symbol, T.untyped])
|
25
|
+
)
|
26
|
+
.void
|
27
|
+
end
|
16
28
|
def initialize(requirements:, latest_version:, source_details:)
|
17
29
|
@requirements = requirements
|
18
30
|
@source_details = source_details
|
19
31
|
return unless latest_version
|
20
32
|
|
21
|
-
@latest_version = version_class.new(latest_version)
|
33
|
+
@latest_version = T.let(version_class.new(latest_version), Dependabot::Nuget::Version)
|
22
34
|
end
|
23
35
|
|
36
|
+
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
24
37
|
def updated_requirements
|
25
38
|
return requirements unless latest_version
|
26
39
|
|
@@ -52,32 +65,42 @@ module Dependabot
|
|
52
65
|
|
53
66
|
private
|
54
67
|
|
55
|
-
|
68
|
+
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
69
|
+
attr_reader :requirements
|
70
|
+
|
71
|
+
sig { returns(T.nilable(Dependabot::Nuget::Version)) }
|
72
|
+
attr_reader :latest_version
|
73
|
+
|
74
|
+
sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
75
|
+
attr_reader :source_details
|
56
76
|
|
77
|
+
sig { returns(T.class_of(Dependabot::Nuget::Version)) }
|
57
78
|
def version_class
|
58
|
-
Nuget::Version
|
79
|
+
Dependabot::Nuget::Version
|
59
80
|
end
|
60
81
|
|
82
|
+
sig { params(req_string: String).returns(String) }
|
61
83
|
def update_wildcard_requirement(req_string)
|
62
84
|
return req_string if req_string == "*-*"
|
63
85
|
|
64
86
|
return req_string if req_string == "*"
|
65
87
|
|
66
|
-
precision = req_string.split("*").first.split(/\.|\-/).count
|
88
|
+
precision = T.must(req_string.split("*").first).split(/\.|\-/).count
|
67
89
|
wildcard_section = req_string.partition(/(?=[.\-]\*)/).last
|
68
90
|
|
69
|
-
version_parts = latest_version.segments.first(precision)
|
91
|
+
version_parts = T.must(latest_version).segments.first(precision)
|
70
92
|
version = version_parts.join(".")
|
71
93
|
|
72
94
|
version + wildcard_section
|
73
95
|
end
|
74
96
|
|
97
|
+
sig { returns(T::Hash[Symbol, T.untyped]) }
|
75
98
|
def updated_source
|
76
99
|
{
|
77
100
|
type: "nuget_repo",
|
78
|
-
url: source_details
|
79
|
-
nuspec_url: source_details
|
80
|
-
source_url: source_details
|
101
|
+
url: source_details&.fetch(:repo_url),
|
102
|
+
nuspec_url: source_details&.fetch(:nuspec_url),
|
103
|
+
source_url: source_details&.fetch(:source_url)
|
81
104
|
}
|
82
105
|
end
|
83
106
|
end
|
@@ -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
|
@@ -1,8 +1,9 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strong
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "excon"
|
5
5
|
require "nokogiri"
|
6
|
+
require "sorbet-runtime"
|
6
7
|
|
7
8
|
require "dependabot/update_checkers/base"
|
8
9
|
require "dependabot/nuget/version"
|
@@ -13,15 +14,25 @@ require "dependabot/shared_helpers"
|
|
13
14
|
module Dependabot
|
14
15
|
module Nuget
|
15
16
|
class TfmFinder
|
17
|
+
extend T::Sig
|
18
|
+
|
16
19
|
require "dependabot/nuget/file_parser/packages_config_parser"
|
17
20
|
require "dependabot/nuget/file_parser/project_file_parser"
|
18
21
|
|
22
|
+
sig do
|
23
|
+
params(
|
24
|
+
dependency_files: T::Array[Dependabot::DependencyFile],
|
25
|
+
credentials: T::Array[Dependabot::Credential],
|
26
|
+
repo_contents_path: T.nilable(String)
|
27
|
+
).void
|
28
|
+
end
|
19
29
|
def initialize(dependency_files:, credentials:, repo_contents_path:)
|
20
30
|
@dependency_files = dependency_files
|
21
31
|
@credentials = credentials
|
22
32
|
@repo_contents_path = repo_contents_path
|
23
33
|
end
|
24
34
|
|
35
|
+
sig { params(dependency: Dependabot::Dependency).returns(T::Array[String]) }
|
25
36
|
def frameworks(dependency)
|
26
37
|
tfms = Set.new
|
27
38
|
tfms += project_file_tfms(dependency)
|
@@ -31,14 +42,23 @@ module Dependabot
|
|
31
42
|
|
32
43
|
private
|
33
44
|
|
34
|
-
|
45
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
46
|
+
attr_reader :dependency_files
|
47
|
+
|
48
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
49
|
+
attr_reader :credentials
|
50
|
+
|
51
|
+
sig { returns(T.nilable(String)) }
|
52
|
+
attr_reader :repo_contents_path
|
35
53
|
|
54
|
+
sig { params(dependency: Dependabot::Dependency).returns(T::Array[String]) }
|
36
55
|
def project_file_tfms(dependency)
|
37
56
|
project_files_with_dependency(dependency).flat_map do |file|
|
38
57
|
project_file_parser.target_frameworks(project_file: file)
|
39
58
|
end
|
40
59
|
end
|
41
60
|
|
61
|
+
sig { params(dependency: Dependabot::Dependency).returns(T::Array[Dependabot::DependencyFile]) }
|
42
62
|
def project_files_with_dependency(dependency)
|
43
63
|
project_files.select do |file|
|
44
64
|
packages_config_contains_dependency?(file, dependency) ||
|
@@ -46,6 +66,7 @@ module Dependabot
|
|
46
66
|
end
|
47
67
|
end
|
48
68
|
|
69
|
+
sig { params(file: Dependabot::DependencyFile, dependency: Dependabot::Dependency).returns(T::Boolean) }
|
49
70
|
def packages_config_contains_dependency?(file, dependency)
|
50
71
|
config_file = find_packages_config_file(file)
|
51
72
|
return false unless config_file
|
@@ -56,36 +77,48 @@ module Dependabot
|
|
56
77
|
end
|
57
78
|
end
|
58
79
|
|
80
|
+
sig { params(file: Dependabot::DependencyFile, dependency: Dependabot::Dependency).returns(T::Boolean) }
|
59
81
|
def project_file_contains_dependency?(file, dependency)
|
60
82
|
project_file_parser.dependency_set(project_file: file).dependencies.any? do |d|
|
61
83
|
d.name.casecmp(dependency.name)&.zero?
|
62
84
|
end
|
63
85
|
end
|
64
86
|
|
87
|
+
sig { params(file: Dependabot::DependencyFile).returns(T.nilable(Dependabot::DependencyFile)) }
|
65
88
|
def find_packages_config_file(file)
|
66
89
|
return file if file.name.end_with?("packages.config")
|
67
90
|
|
68
91
|
filename = File.basename(file.name)
|
69
92
|
search_path = file.name.sub(filename, "packages.config")
|
70
93
|
|
71
|
-
dependency_files.find { |f| f.name.casecmp(search_path)
|
94
|
+
dependency_files.find { |f| f.name.casecmp(search_path)&.zero? }
|
72
95
|
end
|
73
96
|
|
97
|
+
sig { returns(T::Array[String]) }
|
74
98
|
def project_import_file_tfms
|
75
|
-
@project_import_file_tfms ||=
|
76
|
-
|
77
|
-
|
99
|
+
@project_import_file_tfms ||=
|
100
|
+
T.let(
|
101
|
+
project_import_files.flat_map do |file|
|
102
|
+
project_file_parser.target_frameworks(project_file: file)
|
103
|
+
end,
|
104
|
+
T.nilable(T::Array[String])
|
105
|
+
)
|
78
106
|
end
|
79
107
|
|
108
|
+
sig { returns(FileParser::ProjectFileParser) }
|
80
109
|
def project_file_parser
|
81
110
|
@project_file_parser ||=
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
111
|
+
T.let(
|
112
|
+
FileParser::ProjectFileParser.new(
|
113
|
+
dependency_files: dependency_files,
|
114
|
+
credentials: credentials,
|
115
|
+
repo_contents_path: repo_contents_path
|
116
|
+
),
|
117
|
+
T.nilable(FileParser::ProjectFileParser)
|
86
118
|
)
|
87
119
|
end
|
88
120
|
|
121
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
89
122
|
def project_files
|
90
123
|
projfile = /\.[a-z]{2}proj$/
|
91
124
|
packageprops = /[Dd]irectory.[Pp]ackages.props/
|
@@ -96,12 +129,14 @@ module Dependabot
|
|
96
129
|
end
|
97
130
|
end
|
98
131
|
|
132
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
99
133
|
def packages_config_files
|
100
134
|
dependency_files.select do |f|
|
101
|
-
f.name.split("/").last
|
135
|
+
f.name.split("/").last&.casecmp("packages.config")&.zero?
|
102
136
|
end
|
103
137
|
end
|
104
138
|
|
139
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
105
140
|
def project_import_files
|
106
141
|
dependency_files -
|
107
142
|
project_files -
|
@@ -111,16 +146,19 @@ module Dependabot
|
|
111
146
|
[dotnet_tools_json]
|
112
147
|
end
|
113
148
|
|
149
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
114
150
|
def nuget_configs
|
115
151
|
dependency_files.select { |f| f.name.match?(/nuget\.config$/i) }
|
116
152
|
end
|
117
153
|
|
154
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
118
155
|
def global_json
|
119
|
-
dependency_files.find { |f| f.name.casecmp("global.json")
|
156
|
+
dependency_files.find { |f| f.name.casecmp("global.json")&.zero? }
|
120
157
|
end
|
121
158
|
|
159
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
122
160
|
def dotnet_tools_json
|
123
|
-
dependency_files.find { |f| f.name.casecmp(".config/dotnet-tools.json")
|
161
|
+
dependency_files.find { |f| f.name.casecmp(".config/dotnet-tools.json")&.zero? }
|
124
162
|
end
|
125
163
|
end
|
126
164
|
end
|