Class: Dependabot::Maven::Shared::SharedPackageDetailsFetcher
- Inherits:
-
Object
- Object
- Dependabot::Maven::Shared::SharedPackageDetailsFetcher
show all
- Extended by:
- T::Helpers, T::Sig
- Defined in:
- lib/dependabot/maven/shared/shared_package_details_fetcher.rb
Constant Summary
collapse
- MAVEN_METADATA_XML =
T.let("maven-metadata.xml", String)
- REPOSITORY_TYPE =
T.let("maven_repository", String)
- URL_KEY =
T.let("url", String)
T.let("auth_headers", String)
- DEFAULT_CENTRAL_REPO_URL =
T.let("https://repo.maven.apache.org/maven2", String)
Instance Method Summary
collapse
Instance Method Details
397
398
399
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 397
def (maven_repo_url)
.(maven_repo_url)
end
|
#central_repo_url ⇒ Object
378
379
380
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 378
def central_repo_url
DEFAULT_CENTRAL_REPO_URL
end
|
#central_repo_urls ⇒ Object
384
385
386
387
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 384
def central_repo_urls
central_url_without_protocol = central_repo_url.gsub(%r{^.*://}, "")
%w(http:// https://).map { |p| p + central_url_without_protocol }
end
|
#check_response(response, repository_url) ⇒ Object
208
209
210
211
212
213
214
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 208
def check_response(response, repository_url)
return unless [401, 403].include?(response.status)
return if forbidden_urls.include?(repository_url)
return if central_repo_urls.include?(repository_url)
forbidden_urls << repository_url
end
|
#credentials ⇒ Object
30
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 30
def credentials; end
|
#credentials_repository_details ⇒ Object
363
364
365
366
367
368
369
370
371
372
373
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 363
def credentials_repository_details
credentials
.select { |cred| cred["type"] == REPOSITORY_TYPE && cred[URL_KEY] }
.map do |cred|
url_value = cred.fetch(URL_KEY).gsub(%r{/+$}, "")
{
URL_KEY => url_value,
AUTH_HEADERS_KEY => (url_value)
}
end
end
|
#dependency ⇒ Object
27
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 27
def dependency; end
|
#dependency_base_url(repository_url) ⇒ Object
58
59
60
61
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 58
def dependency_base_url(repository_url)
group_path, artifact_id = dependency_parts
"#{repository_url}/#{group_path}/#{artifact_id}"
end
|
#dependency_files_url(repository_url, version) ⇒ Object
74
75
76
77
78
79
80
81
82
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 74
def dependency_files_url(repository_url, version)
_, artifact_id = dependency_parts
base_url = dependency_base_url(repository_url)
type = dependency.requirements.first&.dig(:metadata, :packaging_type) || "jar"
classifier = dependency.requirements.first&.dig(:metadata, :classifier)
actual_classifier = classifier.nil? ? "" : "-#{classifier}"
"#{base_url}/#{version}/#{artifact_id}-#{version}#{actual_classifier}.#{type}"
end
|
410
411
412
413
414
415
416
417
418
419
420
421
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 410
def dependency_metadata(repository_details)
@dependency_metadata = T.let(
@dependency_metadata, T.nilable(T::Hash[T.untyped, Nokogiri::XML::Document])
)
@dependency_metadata ||= {}
repository_key = repository_details.hash
return @dependency_metadata[repository_key] if @dependency_metadata.key?(repository_key)
xml_document = fetch_dependency_metadata(repository_details)
@dependency_metadata[repository_key] ||= xml_document if xml_document
@dependency_metadata[repository_key]
end
|
425
426
427
428
429
430
431
432
433
434
435
436
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 425
def dependency_metadata_from_html(repository_details)
@dependency_metadata_from_html = T.let(
@dependency_metadata_from_html, T.nilable(T::Hash[T.untyped, Nokogiri::HTML::Document])
)
@dependency_metadata_from_html ||= {}
repository_key = repository_details.hash
return @dependency_metadata_from_html[repository_key] if @dependency_metadata_from_html.key?(repository_key)
html_document = fetch_dependency_metadata_from_html(repository_details)
@dependency_metadata_from_html[repository_key] ||= html_document if html_document
@dependency_metadata_from_html[repository_key]
end
|
65
66
67
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 65
def dependency_metadata_url(repository_url)
"#{dependency_base_url(repository_url)}/#{MAVEN_METADATA_XML}"
end
|
#dependency_parts ⇒ Object
44
45
46
47
48
49
50
51
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 44
def dependency_parts
@dependency_parts = T.let(@dependency_parts, T.nilable([String, String]))
return @dependency_parts if @dependency_parts
group_id, artifact_id = dependency.name.split(":")
group_path = T.must(group_id).tr(".", "/")
@dependency_parts = [group_path, T.must(artifact_id)]
end
|
#dependency_pom_url(repository_url, version) ⇒ Object
87
88
89
90
91
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 87
def dependency_pom_url(repository_url, version)
_, artifact_id = dependency_parts
base_url = dependency_base_url(repository_url)
"#{base_url}/#{version}/#{artifact_id}-#{version}.pom"
end
|
123
124
125
126
127
128
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 123
def (xml, url)
xml.css("versions > version")
.select { |node| version_class.correct?(node.content) }
.map { |node| version_class.new(node.content) }
.map { |version| { version: version, source_url: url } }
end
|
193
194
195
196
197
198
199
200
201
202
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 193
def (link)
raw_date_text = link.next&.text.to_s
date_match = raw_date_text.match(/\b(?:\d{4}-\d{2}-\d{2}|\d{2}-[A-Za-z]{3}-\d{4}) \d{2}:\d{2}\b/)
return Time.parse(date_match[0]) if date_match
Time.parse(raw_date_text.strip)
rescue StandardError
nil
end
|
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 163
def (html_doc)
versions_detail_hash = T.let({}, T::Hash[String, T::Hash[Symbol, T.untyped]])
html_doc.css("a[href]").each do |link|
version = (link)
next unless version && version_class.correct?(version)
release_date = (link)
versions_detail_hash[version] = { release_date: release_date }
end
versions_detail_hash
end
|
179
180
181
182
183
184
185
186
187
188
189
190
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 179
def (link)
href = link["href"]&.strip
return unless href&.end_with?("/")
identifier = [link["title"], link.text, href].find { |value| value && !value.strip.empty? }
return unless identifier
version = identifier.strip.gsub(%r{/$}, "")
return if ["..", "."].include?(version)
version
end
|
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 97
def fetch_dependency_metadata(repository_details)
url = repository_details.fetch(URL_KEY)
= repository_details.fetch(AUTH_HEADERS_KEY)
response = Dependabot::RegistryClient.get(
url: dependency_metadata_url(url),
headers:
)
check_response(response, url)
return unless response.status < 400
Nokogiri::XML(response.body)
rescue URI::InvalidURIError
nil
rescue Excon::Error::Socket, Excon::Error::Timeout,
Excon::Error::TooManyRedirects => e
handle_registry_error(url, e, response)
nil
end
|
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 136
def fetch_dependency_metadata_from_html(repository_details)
url = repository_details.fetch(URL_KEY)
= repository_details.fetch(AUTH_HEADERS_KEY)
base_directory_url = dependency_base_url(url)
base_directory_url += "/" unless base_directory_url.end_with?("/")
response = Dependabot::RegistryClient.get(
url: base_directory_url,
headers:
)
check_response(response, url)
return unless response.status < 400
Nokogiri::HTML(response.body)
rescue URI::InvalidURIError
nil
rescue Excon::Error::Socket, Excon::Error::Timeout,
Excon::Error::TooManyRedirects => e
handle_registry_error(url, e, response)
nil
end
|
#forbidden_urls ⇒ Object
390
391
392
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 390
def forbidden_urls
@forbidden_urls ||= T.let([], T.nilable(T::Array[String]))
end
|
#handle_registry_error(url, error, response) ⇒ Object
224
225
226
227
228
229
230
231
232
233
234
235
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 224
def handle_registry_error(url, error, response)
return unless central_repo_urls.include?(url)
response_status = response&.status || 0
response_body = if response
"RegistryError: #{response.status} response status with body #{response.body}"
else
"RegistryError: #{error.message}"
end
raise RegistryError.new(response_status, response_body)
end
|
#released?(version) ⇒ Boolean
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 324
def released?(version)
@released_check = T.let(@released_check, T.nilable(T::Hash[Dependabot::Version, T::Boolean]))
@released_check ||= {}
return T.must(@released_check[version]) if @released_check.key?(version)
@released_check[version] =
repositories.any? do |repository_details|
url = repository_details.fetch(URL_KEY)
= repository_details.fetch(AUTH_HEADERS_KEY)
response = Dependabot::RegistryClient.head(
url: dependency_files_url(url, version),
headers:
)
next true if response.status < 400
next false unless response.status == 404
next false if dependency.requirements.first&.dig(:metadata, :classifier)
pom_response = Dependabot::RegistryClient.head(
url: dependency_pom_url(url, version),
headers:
)
pom_response.status < 400
rescue Excon::Error::Socket, Excon::Error::Timeout,
Excon::Error::TooManyRedirects
false
rescue URI::InvalidURIError => e
raise DependencyFileNotResolvable, e.message
end
end
|
#repositories ⇒ Object
35
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 35
def repositories; end
|
#version_class ⇒ Object
441
442
443
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 441
def version_class
dependency.version_class
end
|
#versions ⇒ Object
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 243
def versions
@version_details = T.let(@version_details, T.nilable(T::Array[T::Hash[Symbol, T.untyped]]))
return @version_details if @version_details
@version_details = versions_details_from_xml
begin
versions_details_hash = versions_details_hash_from_html if @version_details.any?
if versions_details_hash
@version_details = @version_details.map do |vd|
html_details = versions_details_hash[vd[:version].to_s]
next vd unless html_details
release_date = html_details[:release_date]
next vd unless release_date
vd.merge(
release_date: html_details[:release_date],
source_url: vd[:source_url]
)
end
end
rescue StandardError => e
Dependabot.logger.error(
"Error fetching version details from HTML: #{e.message}"
)
end
@version_details = @version_details.sort_by { |d| d.fetch(:version) }
@version_details
end
|
#versions_details_from_xml ⇒ Object
280
281
282
283
284
285
286
287
288
289
290
291
292
293
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 280
def versions_details_from_xml
forbidden_urls.clear
version_details = repositories.flat_map do |repository_details|
url = repository_details.fetch(URL_KEY)
xml = dependency_metadata(repository_details)
next [] if xml.nil?
(xml, url)
end
raise PrivateSourceAuthenticationFailure, forbidden_urls.first if version_details.none? && forbidden_urls.any?
version_details
end
|
#versions_details_hash_from_html ⇒ Object
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
|
# File 'lib/dependabot/maven/shared/shared_package_details_fetcher.rb', line 297
def versions_details_hash_from_html
forbidden_urls.clear
versions_detail_hash = T.let(
{}, T::Hash[String, T::Hash[Symbol, T.untyped]]
)
repositories.each do |repository_details|
html = dependency_metadata_from_html(repository_details)
next if html.nil?
versions_detail_hash = (html)
break if versions_detail_hash.any?
end
if versions_detail_hash.any? && forbidden_urls.any?
raise PrivateSourceAuthenticationFailure,
forbidden_urls.first
end
versions_detail_hash
end
|