dependabot-core 0.84.1 → 0.85.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.
@@ -1,127 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/file_parsers/java/maven"
4
- require "dependabot/update_checkers/java/maven"
5
- require "dependabot/update_checkers/java/maven/requirements_updater"
6
- require "dependabot/file_updaters/java/maven/declaration_finder"
7
-
8
- module Dependabot
9
- module UpdateCheckers
10
- module Java
11
- class Maven
12
- class PropertyUpdater
13
- require_relative "version_finder"
14
-
15
- def initialize(dependency:, dependency_files:, credentials:,
16
- target_version_details:, ignored_versions:)
17
- @dependency = dependency
18
- @dependency_files = dependency_files
19
- @credentials = credentials
20
- @ignored_versions = ignored_versions
21
- @target_version = target_version_details&.fetch(:version)
22
- @source_url = target_version_details&.fetch(:source_url)
23
- end
24
-
25
- def update_possible?
26
- return false unless target_version
27
-
28
- @update_possible ||=
29
- dependencies_using_property.all? do |dep|
30
- versions = VersionFinder.new(
31
- dependency: dep,
32
- dependency_files: dependency_files,
33
- credentials: credentials,
34
- ignored_versions: ignored_versions
35
- ).versions.map { |v| v.fetch(:version) }
36
-
37
- versions.include?(target_version) || versions.none?
38
- end
39
- end
40
-
41
- def updated_dependencies
42
- raise "Update not possible!" unless update_possible?
43
-
44
- @updated_dependencies ||=
45
- dependencies_using_property.map do |dep|
46
- Dependency.new(
47
- name: dep.name,
48
- version: updated_version(dep),
49
- requirements: updated_requirements(dep),
50
- previous_version: dep.version,
51
- previous_requirements: dep.requirements,
52
- package_manager: dep.package_manager
53
- )
54
- end
55
- end
56
-
57
- private
58
-
59
- attr_reader :dependency, :dependency_files, :target_version,
60
- :source_url, :credentials, :ignored_versions
61
-
62
- def dependencies_using_property
63
- @dependencies_using_property ||=
64
- FileParsers::Java::Maven.new(
65
- dependency_files: dependency_files,
66
- source: nil
67
- ).parse.select do |dep|
68
- dep.requirements.any? do |r|
69
- next unless r.dig(:metadata, :property_name) == property_name
70
-
71
- r.dig(:metadata, :property_source) == property_source
72
- end
73
- end
74
- end
75
-
76
- def property_name
77
- @property_name ||= dependency.requirements.
78
- find { |r| r.dig(:metadata, :property_name) }&.
79
- dig(:metadata, :property_name)
80
-
81
- raise "No requirement with a property name!" unless @property_name
82
-
83
- @property_name
84
- end
85
-
86
- def property_source
87
- @property_source ||=
88
- dependency.requirements.
89
- find { |r| r.dig(:metadata, :property_name) == property_name }&.
90
- dig(:metadata, :property_source)
91
- end
92
-
93
- def version_string(dep)
94
- declaring_requirement =
95
- dep.requirements.
96
- find { |r| r.dig(:metadata, :property_name) == property_name }
97
-
98
- FileUpdaters::Java::Maven::DeclarationFinder.new(
99
- dependency: dep,
100
- declaring_requirement: declaring_requirement,
101
- dependency_files: dependency_files
102
- ).declaration_nodes.first.at_css("version")&.content
103
- end
104
-
105
- def pom
106
- dependency_files.find { |f| f.name == "pom.xml" }
107
- end
108
-
109
- def updated_version(dep)
110
- version_string(dep).gsub("${#{property_name}}", target_version.to_s)
111
- end
112
-
113
- def updated_requirements(dep)
114
- @updated_requirements ||= {}
115
- @updated_requirements[dep.name] ||=
116
- RequirementsUpdater.new(
117
- requirements: dep.requirements,
118
- latest_version: updated_version(dep),
119
- source_url: source_url,
120
- properties_to_update: [property_name]
121
- ).updated_requirements
122
- end
123
- end
124
- end
125
- end
126
- end
127
- end
@@ -1,92 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- #######################################################
4
- # For more details on Maven version constraints, see: #
5
- # https://maven.apache.org/pom.html#Dependencies #
6
- #######################################################
7
-
8
- require "dependabot/update_checkers/java/maven"
9
- require "dependabot/utils/java/version"
10
- require "dependabot/utils/java/requirement"
11
-
12
- module Dependabot
13
- module UpdateCheckers
14
- module Java
15
- class Maven
16
- class RequirementsUpdater
17
- def initialize(requirements:, latest_version:, source_url:,
18
- properties_to_update:)
19
- @requirements = requirements
20
- @source_url = source_url
21
- @properties_to_update = properties_to_update
22
- return unless latest_version
23
-
24
- @latest_version = version_class.new(latest_version)
25
- end
26
-
27
- def updated_requirements
28
- return requirements unless latest_version
29
-
30
- # Note: Order is important here. The FileUpdater needs the updated
31
- # requirement at index `i` to correspond to the previous requirement
32
- # at the same index.
33
- requirements.map do |req|
34
- next req if req.fetch(:requirement).nil?
35
- next req if req.fetch(:requirement).include?(",")
36
-
37
- property_name = req.dig(:metadata, :property_name)
38
- if property_name && !properties_to_update.include?(property_name)
39
- next req
40
- end
41
-
42
- new_req = update_requirement(req[:requirement])
43
- req.merge(requirement: new_req, source: updated_source)
44
- end
45
- end
46
-
47
- private
48
-
49
- attr_reader :requirements, :latest_version, :source_url,
50
- :properties_to_update
51
-
52
- def update_requirement(req_string)
53
- if req_string.include?(".+")
54
- update_dynamic_requirement(req_string)
55
- else
56
- # Since range requirements are excluded this must be exact
57
- update_exact_requirement(req_string)
58
- end
59
- end
60
-
61
- def update_exact_requirement(req_string)
62
- old_version = requirement_class.new(req_string).
63
- requirements.first.last
64
- req_string.gsub(old_version.to_s, latest_version.to_s)
65
- end
66
-
67
- # This is really only a Gradle thing, but Gradle relies on this
68
- # RequirementsUpdater too
69
- def update_dynamic_requirement(req_string)
70
- precision = req_string.split(".").take_while { |s| s != "+" }.count
71
-
72
- version_parts = latest_version.segments.first(precision)
73
-
74
- version_parts.join(".") + ".+"
75
- end
76
-
77
- def version_class
78
- Utils::Java::Version
79
- end
80
-
81
- def requirement_class
82
- Utils::Java::Requirement
83
- end
84
-
85
- def updated_source
86
- { type: "maven_repo", url: source_url }
87
- end
88
- end
89
- end
90
- end
91
- end
92
- end
@@ -1,225 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "nokogiri"
4
- require "dependabot/shared_helpers"
5
- require "dependabot/file_parsers/java/maven/repositories_finder"
6
- require "dependabot/update_checkers/java/maven"
7
- require "dependabot/utils/java/version"
8
- require "dependabot/utils/java/requirement"
9
-
10
- module Dependabot
11
- module UpdateCheckers
12
- module Java
13
- class Maven
14
- class VersionFinder
15
- TYPE_SUFFICES = %w(jre android java).freeze
16
-
17
- def initialize(dependency:, dependency_files:, credentials:,
18
- ignored_versions:)
19
- @dependency = dependency
20
- @dependency_files = dependency_files
21
- @credentials = credentials
22
- @ignored_versions = ignored_versions
23
- @forbidden_urls = []
24
- end
25
-
26
- def latest_version_details
27
- possible_versions = versions
28
-
29
- unless wants_prerelease?
30
- possible_versions =
31
- possible_versions.
32
- reject { |v| v.fetch(:version).prerelease? }
33
- end
34
-
35
- unless wants_date_based_version?
36
- possible_versions =
37
- possible_versions.
38
- reject { |v| v.fetch(:version) > version_class.new(1900) }
39
- end
40
-
41
- possible_versions =
42
- possible_versions.
43
- select { |v| matches_dependency_version_type?(v.fetch(:version)) }
44
-
45
- ignored_versions.each do |req|
46
- ignore_req = Utils::Java::Requirement.new(req.split(","))
47
- possible_versions =
48
- possible_versions.
49
- reject { |v| ignore_req.satisfied_by?(v.fetch(:version)) }
50
- end
51
-
52
- possible_versions.reverse.find { |v| released?(v.fetch(:version)) }
53
- end
54
-
55
- def versions
56
- version_details =
57
- repositories.map do |repository_details|
58
- url = repository_details.fetch("url")
59
- dependency_metadata(repository_details).
60
- css("versions > version").
61
- select { |node| version_class.correct?(node.content) }.
62
- map { |node| version_class.new(node.content) }.
63
- map { |version| { version: version, source_url: url } }
64
- end.flatten
65
-
66
- if version_details.none? && forbidden_urls.any?
67
- raise PrivateSourceAuthenticationFailure, forbidden_urls.first
68
- end
69
-
70
- version_details.sort_by { |details| details.fetch(:version) }
71
- end
72
-
73
- private
74
-
75
- attr_reader :dependency, :dependency_files, :credentials,
76
- :ignored_versions, :forbidden_urls
77
-
78
- def wants_prerelease?
79
- return false unless dependency.version
80
- return false unless version_class.correct?(dependency.version)
81
-
82
- version_class.new(dependency.version).prerelease?
83
- end
84
-
85
- def wants_date_based_version?
86
- return false unless dependency.version
87
- return false unless version_class.correct?(dependency.version)
88
-
89
- version_class.new(dependency.version) >= version_class.new(100)
90
- end
91
-
92
- def released?(version)
93
- repositories.any? do |repository_details|
94
- url = repository_details.fetch("url")
95
- response = Excon.get(
96
- dependency_files_url(url, version),
97
- user: repository_details.fetch("username"),
98
- password: repository_details.fetch("password"),
99
- idempotent: true,
100
- **SharedHelpers.excon_defaults
101
- )
102
-
103
- artifact_id = dependency.name.split(":").last
104
- type = dependency.requirements.first.
105
- dig(:metadata, :packaging_type)
106
- response.body.include?("#{artifact_id}-#{version}.#{type}")
107
- rescue Excon::Error::Socket, Excon::Error::Timeout
108
- false
109
- end
110
- end
111
-
112
- def dependency_metadata(repository_details)
113
- @dependency_metadata ||= {}
114
- @dependency_metadata[repository_details.hash] ||=
115
- begin
116
- response = Excon.get(
117
- dependency_metadata_url(repository_details.fetch("url")),
118
- user: repository_details.fetch("username"),
119
- password: repository_details.fetch("password"),
120
- idempotent: true,
121
- **SharedHelpers.excon_defaults
122
- )
123
- check_response(response, repository_details.fetch("url"))
124
- Nokogiri::XML(response.body)
125
- rescue Excon::Error::Socket, Excon::Error::Timeout
126
- central =
127
- FileParsers::Java::Maven::RepositoriesFinder::CENTRAL_REPO_URL
128
- raise if repository_details.fetch("url") == central
129
-
130
- Nokogiri::XML("")
131
- end
132
- end
133
-
134
- def check_response(response, repository_url)
135
- central =
136
- FileParsers::Java::Maven::RepositoriesFinder::CENTRAL_REPO_URL
137
-
138
- return unless [401, 403].include?(response.status)
139
- return if @forbidden_urls.include?(repository_url)
140
- return if repository_url == central
141
-
142
- @forbidden_urls << repository_url
143
- end
144
-
145
- def repositories
146
- return @repositories if @repositories
147
-
148
- details = pom_repository_details + credentials_repository_details
149
-
150
- @repositories =
151
- details.reject do |repo|
152
- next if repo["password"]
153
-
154
- # Reject this entry if an identical one with a password exists
155
- details.any? { |r| r["url"] == repo["url"] && r["password"] }
156
- end
157
- end
158
-
159
- def pom_repository_details
160
- @pom_repository_details ||=
161
- FileParsers::Java::Maven::RepositoriesFinder.
162
- new(dependency_files: dependency_files).
163
- repository_urls(pom: pom).
164
- map do |url|
165
- { "url" => url, "username" => nil, "password" => nil }
166
- end
167
- end
168
-
169
- def credentials_repository_details
170
- credentials.
171
- select { |cred| cred["type"] == "maven_repository" }.
172
- map do |cred|
173
- {
174
- "url" => cred.fetch("url").gsub(%r{/+$}, ""),
175
- "username" => cred.fetch("username", nil),
176
- "password" => cred.fetch("password", nil)
177
- }
178
- end
179
- end
180
-
181
- def matches_dependency_version_type?(comparison_version)
182
- return true unless dependency.version
183
-
184
- current_type =
185
- TYPE_SUFFICES.
186
- find { |t| dependency.version.split(/[.\-]/).include?(t) }
187
-
188
- version_type =
189
- TYPE_SUFFICES.
190
- find { |t| comparison_version.to_s.split(/[.\-]/).include?(t) }
191
-
192
- current_type == version_type
193
- end
194
-
195
- def pom
196
- filename = dependency.requirements.first.fetch(:file)
197
- dependency_files.find { |f| f.name == filename }
198
- end
199
-
200
- def dependency_metadata_url(repository_url)
201
- group_id, artifact_id = dependency.name.split(":")
202
-
203
- "#{repository_url}/"\
204
- "#{group_id.tr('.', '/')}/"\
205
- "#{artifact_id}/"\
206
- "maven-metadata.xml"
207
- end
208
-
209
- def dependency_files_url(repository_url, version)
210
- group_id, artifact_id = dependency.name.split(":")
211
-
212
- "#{repository_url}/"\
213
- "#{group_id.tr('.', '/')}/"\
214
- "#{artifact_id}/"\
215
- "#{version}/"
216
- end
217
-
218
- def version_class
219
- Utils::Java::Version
220
- end
221
- end
222
- end
223
- end
224
- end
225
- end
@@ -1,110 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/utils/java/version"
4
-
5
- module Dependabot
6
- module Utils
7
- module Java
8
- class Requirement < Gem::Requirement
9
- quoted = OPS.keys.map { |k| Regexp.quote k }.join("|")
10
- PATTERN_RAW =
11
- "\\s*(#{quoted})?\\s*(#{Utils::Java::Version::VERSION_PATTERN})\\s*"
12
- PATTERN = /\A#{PATTERN_RAW}\z/.freeze
13
-
14
- def self.parse(obj)
15
- if obj.is_a?(Gem::Version)
16
- return ["=", Utils::Java::Version.new(obj.to_s)]
17
- end
18
-
19
- unless (matches = PATTERN.match(obj.to_s))
20
- msg = "Illformed requirement [#{obj.inspect}]"
21
- raise BadRequirementError, msg
22
- end
23
-
24
- return DefaultRequirement if matches[1] == ">=" && matches[2] == "0"
25
-
26
- [matches[1] || "=", Utils::Java::Version.new(matches[2])]
27
- end
28
-
29
- def self.requirements_array(requirement_string)
30
- split_java_requirement(requirement_string).map do |str|
31
- new(str)
32
- end
33
- end
34
-
35
- def initialize(*requirements)
36
- requirements = requirements.flatten.flat_map do |req_string|
37
- convert_java_constraint_to_ruby_constraint(req_string)
38
- end
39
-
40
- super(requirements)
41
- end
42
-
43
- def satisfied_by?(version)
44
- version = Utils::Java::Version.new(version.to_s)
45
- super
46
- end
47
-
48
- private
49
-
50
- def self.split_java_requirement(req_string)
51
- req_string.split(/(?<=\]|\)),/).flat_map do |str|
52
- next str if str.start_with?("(", "[")
53
-
54
- exacts, *rest = str.split(/,(?=\[|\()/)
55
- [*exacts.split(","), *rest]
56
- end
57
- end
58
- private_class_method :split_java_requirement
59
-
60
- def convert_java_constraint_to_ruby_constraint(req_string)
61
- return unless req_string
62
-
63
- if self.class.send(:split_java_requirement, req_string).count > 1
64
- raise "Can't convert multiple Java reqs to a single Ruby one"
65
- end
66
-
67
- if req_string&.include?(",")
68
- return convert_java_range_to_ruby_range(req_string)
69
- end
70
-
71
- convert_java_equals_req_to_ruby(req_string)
72
- end
73
-
74
- def convert_java_range_to_ruby_range(req_string)
75
- lower_b, upper_b = req_string.split(",").map(&:strip)
76
-
77
- lower_b =
78
- if ["(", "["].include?(lower_b) then nil
79
- elsif lower_b.start_with?("(") then "> #{lower_b.sub(/\(\s*/, '')}"
80
- else ">= #{lower_b.sub(/\[\s*/, '').strip}"
81
- end
82
-
83
- upper_b =
84
- if [")", "]"].include?(upper_b) then nil
85
- elsif upper_b.end_with?(")") then "< #{upper_b.sub(/\s*\)/, '')}"
86
- else "<= #{upper_b.sub(/\s*\]/, '').strip}"
87
- end
88
-
89
- [lower_b, upper_b].compact
90
- end
91
-
92
- def convert_java_equals_req_to_ruby(req_string)
93
- return convert_wildcard_req(req_string) if req_string&.include?("+")
94
-
95
- # If a soft requirement is being used, treat it as an equality matcher
96
- return req_string unless req_string&.start_with?("[")
97
-
98
- req_string.gsub(/[\[\]\(\)]/, "")
99
- end
100
-
101
- def convert_wildcard_req(req_string)
102
- version = req_string.gsub(/(?:\.|^)\+/, "")
103
- return ">= 0" if version.empty?
104
-
105
- "~> #{version}.0"
106
- end
107
- end
108
- end
109
- end
110
- end