dependabot-core 0.94.13 → 0.95.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. metadata +13 -337
  3. data/CHANGELOG.md +0 -7079
  4. data/LICENSE +0 -39
  5. data/README.md +0 -114
  6. data/helpers/test/run.rb +0 -18
  7. data/helpers/utils/git-credential-store-immutable +0 -10
  8. data/lib/dependabot/clients/bitbucket.rb +0 -105
  9. data/lib/dependabot/clients/github_with_retries.rb +0 -121
  10. data/lib/dependabot/clients/gitlab.rb +0 -72
  11. data/lib/dependabot/dependency.rb +0 -115
  12. data/lib/dependabot/dependency_file.rb +0 -60
  13. data/lib/dependabot/errors.rb +0 -179
  14. data/lib/dependabot/file_fetchers/README.md +0 -65
  15. data/lib/dependabot/file_fetchers/base.rb +0 -368
  16. data/lib/dependabot/file_fetchers.rb +0 -18
  17. data/lib/dependabot/file_parsers/README.md +0 -45
  18. data/lib/dependabot/file_parsers/base/dependency_set.rb +0 -77
  19. data/lib/dependabot/file_parsers/base.rb +0 -31
  20. data/lib/dependabot/file_parsers.rb +0 -18
  21. data/lib/dependabot/file_updaters/README.md +0 -58
  22. data/lib/dependabot/file_updaters/base.rb +0 -52
  23. data/lib/dependabot/file_updaters.rb +0 -18
  24. data/lib/dependabot/git_commit_checker.rb +0 -412
  25. data/lib/dependabot/metadata_finders/README.md +0 -53
  26. data/lib/dependabot/metadata_finders/base/changelog_finder.rb +0 -321
  27. data/lib/dependabot/metadata_finders/base/changelog_pruner.rb +0 -177
  28. data/lib/dependabot/metadata_finders/base/commits_finder.rb +0 -221
  29. data/lib/dependabot/metadata_finders/base/release_finder.rb +0 -255
  30. data/lib/dependabot/metadata_finders/base.rb +0 -117
  31. data/lib/dependabot/metadata_finders.rb +0 -18
  32. data/lib/dependabot/pull_request_creator/branch_namer.rb +0 -170
  33. data/lib/dependabot/pull_request_creator/commit_signer.rb +0 -63
  34. data/lib/dependabot/pull_request_creator/github.rb +0 -277
  35. data/lib/dependabot/pull_request_creator/gitlab.rb +0 -136
  36. data/lib/dependabot/pull_request_creator/labeler.rb +0 -373
  37. data/lib/dependabot/pull_request_creator/message_builder.rb +0 -906
  38. data/lib/dependabot/pull_request_creator.rb +0 -153
  39. data/lib/dependabot/pull_request_updater/github.rb +0 -165
  40. data/lib/dependabot/pull_request_updater.rb +0 -43
  41. data/lib/dependabot/shared_helpers.rb +0 -224
  42. data/lib/dependabot/source.rb +0 -120
  43. data/lib/dependabot/update_checkers/README.md +0 -67
  44. data/lib/dependabot/update_checkers/base.rb +0 -220
  45. data/lib/dependabot/update_checkers.rb +0 -18
  46. data/lib/dependabot/utils.rb +0 -33
  47. data/lib/dependabot/version.rb +0 -5
  48. data/lib/dependabot.rb +0 -4
  49. data/lib/rubygems_version_patch.rb +0 -14
@@ -1,77 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/dependency"
4
- require "dependabot/file_parsers/base"
5
- require "dependabot/utils"
6
-
7
- module Dependabot
8
- module FileParsers
9
- class Base
10
- class DependencySet
11
- def initialize(dependencies = [])
12
- unless dependencies.is_a?(Array) &&
13
- dependencies.all? { |dep| dep.is_a?(Dependency) }
14
- raise ArgumentError, "must be an array of Dependency objects"
15
- end
16
-
17
- @dependencies = dependencies
18
- end
19
-
20
- attr_reader :dependencies
21
-
22
- def <<(dep)
23
- unless dep.is_a?(Dependency)
24
- raise ArgumentError, "must be a Dependency object"
25
- end
26
-
27
- existing_dependency = dependencies.find { |d| d.name == dep.name }
28
-
29
- return self if existing_dependency&.to_h == dep.to_h
30
-
31
- if existing_dependency
32
- dependencies[dependencies.index(existing_dependency)] =
33
- combined_dependency(existing_dependency, dep)
34
- else
35
- dependencies << dep
36
- end
37
-
38
- self
39
- end
40
-
41
- def +(other)
42
- unless other.is_a?(DependencySet)
43
- raise ArgumentError, "must be a DependencySet"
44
- end
45
-
46
- other.dependencies.each { |dep| self << dep }
47
- self
48
- end
49
-
50
- private
51
-
52
- def combined_dependency(old_dep, new_dep)
53
- package_manager = old_dep.package_manager
54
- v_cls = Utils.version_class_for_package_manager(package_manager)
55
-
56
- # If we already have a requirement use the existing version
57
- # (if present). Otherwise, use whatever the lowest version is
58
- new_version =
59
- if old_dep.requirements.any? then old_dep.version || new_dep.version
60
- elsif !v_cls.correct?(new_dep.version) then old_dep.version
61
- elsif !v_cls.correct?(old_dep.version) then new_dep.version
62
- elsif v_cls.new(new_dep.version) > v_cls.new(old_dep.version)
63
- old_dep.version
64
- else new_dep.version
65
- end
66
-
67
- Dependency.new(
68
- name: old_dep.name,
69
- version: new_version,
70
- requirements: (old_dep.requirements + new_dep.requirements).uniq,
71
- package_manager: package_manager
72
- )
73
- end
74
- end
75
- end
76
- end
77
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dependabot
4
- module FileParsers
5
- class Base
6
- attr_reader :dependency_files, :credentials, :source
7
-
8
- def initialize(dependency_files:, source:, credentials: [])
9
- @dependency_files = dependency_files
10
- @credentials = credentials
11
- @source = source
12
-
13
- check_required_files
14
- end
15
-
16
- def parse
17
- raise NotImplementedError
18
- end
19
-
20
- private
21
-
22
- def check_required_files
23
- raise NotImplementedError
24
- end
25
-
26
- def get_original_file(filename)
27
- dependency_files.find { |f| f.name == filename }
28
- end
29
- end
30
- end
31
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dependabot
4
- module FileParsers
5
- @file_parsers = {}
6
-
7
- def self.for_package_manager(package_manager)
8
- file_parser = @file_parsers[package_manager]
9
- return file_parser if file_parser
10
-
11
- raise "Unsupported package_manager #{package_manager}"
12
- end
13
-
14
- def self.register(package_manager, file_parser)
15
- @file_parsers[package_manager] = file_parser
16
- end
17
- end
18
- end
@@ -1,58 +0,0 @@
1
- # File updaters
2
-
3
- File updaters update a dependency file to use the latest version of a given
4
- dependency. They rely on information provided to them by update checkers.
5
-
6
- There is a `Dependabot::FileUpdaters` class for each language Dependabot
7
- supports.
8
-
9
- ## Public API
10
-
11
- Each `Dependabot::FileUpdaters` class implements the following methods:
12
-
13
- | Method | Description |
14
- |------------------------------|-----------------------------------------------------------------------------------------------|
15
- | `.updated_files_regex` | An array of regular expressions matching the names of the files this class updates. Intended to be used by integrators when checking whether a commit may cause merge-conflicts with a dependency update pull request. |
16
- | `#updated_dependency_files` | Returns an array of updated `Dependabot::DependencyFile` instances, with their content updated to include the updated dependency. |
17
-
18
- An integration might look as follows:
19
-
20
- ```ruby
21
- require 'dependabot/file_updaters'
22
-
23
- unless update_checker.can_update?(requirements_to_update: :own)
24
- raise "Dependency doesn't need update!"
25
- end
26
- dependencies = update_checker.updated_dependencies(requirements_to_update: :own)
27
-
28
- file_updater_class = Dependabot::FileUpdaters::Ruby::Bundler
29
- file_updater = file_updater_class.new(
30
- dependencies: dependencies,
31
- dependency_files: files,
32
- credentials: [{
33
- "type" => "git_source",
34
- "host" => "github.com",
35
- "username" => "x-access-token",
36
- "password" => "token"
37
- }]
38
- )
39
-
40
- file_updater.updated_dependency_files.each do |file|
41
- puts "Updated #{file.name} with new content:\n\n#{file.content}"
42
- end
43
- ```
44
-
45
- ## Writing a file updater for a new language
46
-
47
- All new file updaters should inherit from `Dependabot::FileUpdaters::Base` and
48
- implement the following methods:
49
-
50
- | Method | Description |
51
- |-----------------------------|-------------------------|
52
- | `.updated_files_regex` | See Public API section. |
53
- | `#updated_dependency_files` | See Public API section. |
54
-
55
- To ensure the above are implemented, you should include
56
- `it_behaves_like "a dependency file updater"` in your specs for the new file
57
- updater.
58
-
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dependabot
4
- module FileUpdaters
5
- class Base
6
- attr_reader :dependencies, :dependency_files, :credentials
7
-
8
- def self.updated_files_regex
9
- raise NotImplementedError
10
- end
11
-
12
- def initialize(dependencies:, dependency_files:, credentials:)
13
- @dependencies = dependencies
14
- @dependency_files = dependency_files
15
- @credentials = credentials
16
-
17
- check_required_files
18
- end
19
-
20
- def updated_dependency_files
21
- raise NotImplementedError
22
- end
23
-
24
- private
25
-
26
- def check_required_files
27
- raise NotImplementedError
28
- end
29
-
30
- def get_original_file(filename)
31
- dependency_files.find { |f| f.name == filename }
32
- end
33
-
34
- def file_changed?(file)
35
- dependencies.any? { |dep| requirement_changed?(file, dep) }
36
- end
37
-
38
- def requirement_changed?(file, dependency)
39
- changed_requirements =
40
- dependency.requirements - dependency.previous_requirements
41
-
42
- changed_requirements.any? { |f| f[:file] == file.name }
43
- end
44
-
45
- def updated_file(file:, content:)
46
- updated_file = file.dup
47
- updated_file.content = content
48
- updated_file
49
- end
50
- end
51
- end
52
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dependabot
4
- module FileUpdaters
5
- @file_updaters = {}
6
-
7
- def self.for_package_manager(package_manager)
8
- file_updater = @file_updaters[package_manager]
9
- return file_updater if file_updater
10
-
11
- raise "Unsupported package_manager #{package_manager}"
12
- end
13
-
14
- def self.register(package_manager, file_updater)
15
- @file_updaters[package_manager] = file_updater
16
- end
17
- end
18
- end
@@ -1,412 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "excon"
4
- require "gitlab"
5
- require "dependabot/clients/github_with_retries"
6
- require "dependabot/metadata_finders"
7
- require "dependabot/errors"
8
- require "dependabot/utils"
9
- require "dependabot/source"
10
-
11
- # rubocop:disable Metrics/ClassLength
12
- module Dependabot
13
- class GitCommitChecker
14
- VERSION_REGEX = /(?<version>[0-9]+\.[0-9]+(?:\.[a-zA-Z0-9\-]+)*)$/.freeze
15
- KNOWN_HOSTS = /github\.com|bitbucket\.org|gitlab.com/.freeze
16
-
17
- def initialize(dependency:, credentials:, ignored_versions: [],
18
- requirement_class: nil, version_class: nil)
19
- @dependency = dependency
20
- @credentials = credentials
21
- @ignored_versions = ignored_versions
22
- @requirement_class = requirement_class
23
- @version_class = version_class
24
- end
25
-
26
- def git_dependency?
27
- return false if dependency_source_details.nil?
28
-
29
- dependency_source_details.fetch(:type) == "git"
30
- end
31
-
32
- def pinned?
33
- raise "Not a git dependency!" unless git_dependency?
34
-
35
- ref = dependency_source_details.fetch(:ref)
36
- branch = dependency_source_details.fetch(:branch)
37
-
38
- return false if ref.nil?
39
- return false if branch == ref
40
- return true if branch
41
- return true if dependency.version&.start_with?(ref)
42
-
43
- # Check the specified `ref` isn't actually a branch
44
- !local_upload_pack.match?("refs/heads/#{ref}")
45
- end
46
-
47
- def pinned_ref_looks_like_version?
48
- return false unless pinned?
49
-
50
- dependency_source_details.fetch(:ref).match?(VERSION_REGEX)
51
- end
52
-
53
- def branch_or_ref_in_release?(version)
54
- pinned_ref_in_release?(version) || branch_behind_release?(version)
55
- end
56
-
57
- def head_commit_for_current_branch
58
- return dependency.version if pinned?
59
-
60
- branch_ref = ref_or_branch ? "refs/heads/#{ref_or_branch}" : "HEAD"
61
-
62
- # Remove the opening clause of the upload pack as this isn't always
63
- # followed by a line break. When it isn't (e.g., with Bitbucket) it causes
64
- # problems for our `sha_for_update_pack_line` logic
65
- line = local_upload_pack.
66
- gsub(/.*git-upload-pack/, "").
67
- lines.find { |l| l.include?(" #{branch_ref}") }
68
-
69
- return sha_for_update_pack_line(line) if line
70
-
71
- raise Dependabot::GitDependencyReferenceNotFound, dependency.name
72
- end
73
-
74
- def local_tag_for_latest_version
75
- tag =
76
- local_tags.
77
- select { |t| t.name.match?(VERSION_REGEX) }.
78
- reject { |t| tag_included_in_ignore_reqs?(t) }.
79
- reject { |t| tag_is_prerelease?(t) && !wants_prerelease? }.
80
- max_by do |t|
81
- version = t.name.match(VERSION_REGEX).named_captures.fetch("version")
82
- version_class.new(version)
83
- end
84
-
85
- return unless tag
86
-
87
- {
88
- tag: tag.name,
89
- commit_sha: tag.commit_sha,
90
- tag_sha: tag.tag_sha
91
- }
92
- end
93
-
94
- private
95
-
96
- attr_reader :dependency, :credentials, :ignored_versions
97
-
98
- def pinned_ref_in_release?(version)
99
- raise "Not a git dependency!" unless git_dependency?
100
-
101
- return false unless pinned?
102
- return false if listing_source_url.nil?
103
-
104
- tag = listing_tag_for_version(version.to_s)
105
- return false unless tag
106
-
107
- commit_included_in_tag?(
108
- commit: dependency_source_details.fetch(:ref),
109
- tag: tag,
110
- allow_identical: true
111
- )
112
- end
113
-
114
- def branch_behind_release?(version)
115
- raise "Not a git dependency!" unless git_dependency?
116
-
117
- return false if ref_or_branch.nil?
118
- return false if listing_source_url.nil?
119
-
120
- tag = listing_tag_for_version(version.to_s)
121
- return false unless tag
122
-
123
- # Check if behind, excluding the case where it's identical, because
124
- # we normally wouldn't switch you from tracking master to a release.
125
- commit_included_in_tag?(
126
- commit: ref_or_branch,
127
- tag: tag,
128
- allow_identical: false
129
- )
130
- end
131
-
132
- def local_upload_pack
133
- @local_upload_pack ||=
134
- fetch_upload_pack_for(dependency_source_details.fetch(:url))
135
- end
136
-
137
- def local_tags
138
- return [] unless local_upload_pack
139
-
140
- tags_for_upload_pack(local_upload_pack)
141
- end
142
-
143
- def tags_for_upload_pack(upload_pack)
144
- peeled_lines = []
145
- unpeeled_lines = []
146
-
147
- upload_pack.lines.each do |line|
148
- next unless line.split(" ").last.start_with?("refs/tags")
149
-
150
- if line.strip.end_with?("^{}") then peeled_lines << line
151
- else unpeeled_lines << line
152
- end
153
- end
154
-
155
- unpeeled_lines.map do |line|
156
- tag_name = line.split(" refs/tags/").last.strip
157
- tag_sha = sha_for_update_pack_line(line)
158
- peeled_line = peeled_lines.find do |pl|
159
- pl.split(" refs/tags/").last.strip == "#{tag_name}^{}"
160
- end
161
-
162
- commit_sha =
163
- peeled_line ? sha_for_update_pack_line(peeled_line) : tag_sha
164
-
165
- if dependency_source_details&.fetch(:ref, nil)&.start_with?("tags/")
166
- tag_name = "tags/#{tag_name}"
167
- end
168
-
169
- OpenStruct.new(name: tag_name, tag_sha: tag_sha, commit_sha: commit_sha)
170
- end
171
- end
172
-
173
- # rubocop:disable Metrics/CyclomaticComplexity
174
- # rubocop:disable Metrics/PerceivedComplexity
175
- def fetch_upload_pack_for(uri)
176
- response = Excon.get(
177
- service_pack_uri(uri),
178
- idempotent: true,
179
- **SharedHelpers.excon_defaults
180
- )
181
-
182
- return response.body if response.status == 200
183
- if response.status >= 500 && uri.match?(KNOWN_HOSTS)
184
- raise "Server error at #{uri}: #{response.body}"
185
- end
186
-
187
- raise Dependabot::GitDependenciesNotReachable, [uri]
188
- rescue Excon::Error::Socket, Excon::Error::Timeout
189
- retry_count ||= 0
190
- retry_count += 1
191
-
192
- sleep(rand(0.9)) && retry if retry_count < 2 && uri.match?(KNOWN_HOSTS)
193
- raise if uri.match?(KNOWN_HOSTS)
194
-
195
- raise Dependabot::GitDependenciesNotReachable, [uri]
196
- end
197
- # rubocop:enable Metrics/CyclomaticComplexity
198
- # rubocop:enable Metrics/PerceivedComplexity
199
-
200
- def service_pack_uri(uri)
201
- service_pack_uri = uri_with_auth(uri)
202
- service_pack_uri = service_pack_uri.gsub(%r{/$}, "")
203
- service_pack_uri += ".git" unless service_pack_uri.end_with?(".git")
204
- service_pack_uri + "/info/refs?service=git-upload-pack"
205
- end
206
-
207
- def uri_with_auth(uri)
208
- bare_uri =
209
- if uri.include?("git@") then uri.split("git@").last.sub(":", "/")
210
- else uri.sub(%r{.*?://}, "")
211
- end
212
- cred = credentials.select { |c| c["type"] == "git_source" }.
213
- find { |c| bare_uri.start_with?(c["host"]) }
214
-
215
- if bare_uri.match?(%r{[^/]+:[^/]+@})
216
- # URI already has authentication details
217
- "https://#{bare_uri}"
218
- elsif cred
219
- # URI doesn't have authentication details, but we have credentials
220
- auth_string = "#{cred.fetch('username')}:#{cred.fetch('password')}"
221
- "https://#{auth_string}@#{bare_uri}"
222
- else
223
- # No credentials, so just return the https URI
224
- "https://#{bare_uri}"
225
- end
226
- end
227
-
228
- def commit_included_in_tag?(tag:, commit:, allow_identical: false)
229
- status =
230
- case Source.from_url(listing_source_url)&.provider
231
- when "github" then github_commit_comparison_status(tag, commit)
232
- when "gitlab" then gitlab_commit_comparison_status(tag, commit)
233
- when "bitbucket" then bitbucket_commit_comparison_status(tag, commit)
234
- else raise "Unknown source"
235
- end
236
-
237
- return true if status == "behind"
238
-
239
- allow_identical && status == "identical"
240
- rescue Octokit::NotFound, Gitlab::Error::NotFound,
241
- Octokit::InternalServerError
242
- false
243
- end
244
-
245
- def github_commit_comparison_status(ref1, ref2)
246
- client = Clients::GithubWithRetries.
247
- for_github_dot_com(credentials: credentials)
248
-
249
- client.compare(listing_source_repo, ref1, ref2).status
250
- end
251
-
252
- def gitlab_commit_comparison_status(ref1, ref2)
253
- access_token = credentials.
254
- select { |cred| cred["type"] == "git_source" }.
255
- find { |cred| cred["host"] == "gitlab.com" }&.
256
- fetch("token")
257
-
258
- client = Gitlab.client(endpoint: "https://gitlab.com/api/v4",
259
- private_token: access_token.to_s)
260
-
261
- comparison = client.compare(listing_source_repo, ref1, ref2)
262
-
263
- if comparison.commits.none? then "behind"
264
- elsif comparison.compare_same_ref then "identical"
265
- else "ahead"
266
- end
267
- end
268
-
269
- def bitbucket_commit_comparison_status(ref1, ref2)
270
- url = "https://api.bitbucket.org/2.0/repositories/"\
271
- "#{listing_source_repo}/commits/?"\
272
- "include=#{ref2}&exclude=#{ref1}"
273
-
274
- response = Excon.get(url,
275
- headers: bitbucket_auth_header,
276
- idempotent: true,
277
- **SharedHelpers.excon_defaults)
278
-
279
- # Conservatively assume that ref2 is ahead in the equality case, of
280
- # if we get an unexpected format (e.g., due to a 404)
281
- if JSON.parse(response.body).fetch("values", ["x"]).none? then "behind"
282
- else "ahead"
283
- end
284
- end
285
-
286
- def bitbucket_auth_header
287
- token = credentials.
288
- select { |cred| cred["type"] == "git_source" }.
289
- find { |cred| cred["host"] == "bitbucket.org" }&.
290
- fetch("token")
291
-
292
- if token.nil? then {}
293
- elsif token.include?(":")
294
- encoded_token = Base64.encode64(token).delete("\n")
295
- { "Authorization" => "Basic #{encoded_token}" }
296
- elsif Base64.decode64(token).ascii_only? &&
297
- Base64.decode64(token).include?(":")
298
- { "Authorization" => "Basic #{token.delete("\n")}" }
299
- else
300
- { "Authorization" => "Bearer #{token}" }
301
- end
302
- end
303
-
304
- def dependency_source_details
305
- sources =
306
- dependency.requirements.map { |r| r.fetch(:source) }.uniq.compact
307
-
308
- return sources.first if sources.count <= 1
309
-
310
- # If there are multiple source types, or multiple source URLs, then it's
311
- # unclear how we should proceed
312
- if sources.map { |s| [s.fetch(:type), s.fetch(:url, nil)] }.uniq.count > 1
313
- raise "Multiple sources! #{sources.join(', ')}"
314
- end
315
-
316
- # Otherwise it's reasonable to take the first source and use that. This
317
- # will happen if we have multiple git sources with difference references
318
- # specified. In that case it's fine to update them all.
319
- sources.first
320
- end
321
-
322
- def ref_or_branch
323
- dependency_source_details.fetch(:ref) ||
324
- dependency_source_details.fetch(:branch)
325
- end
326
-
327
- def listing_source_url
328
- @listing_source_url ||=
329
- begin
330
- # Remove the git source, so the metadata finder looks on the
331
- # registry
332
- candidate_dep = Dependency.new(
333
- name: dependency.name,
334
- version: dependency.version,
335
- requirements: [],
336
- package_manager: dependency.package_manager
337
- )
338
-
339
- MetadataFinders.
340
- for_package_manager(dependency.package_manager).
341
- new(dependency: candidate_dep, credentials: credentials).
342
- source_url
343
- end
344
- end
345
-
346
- def listing_source_repo
347
- return unless listing_source_url
348
-
349
- Source.from_url(listing_source_url)&.repo
350
- end
351
-
352
- def listing_tag_for_version(version)
353
- listing_tags.
354
- find { |t| t.name =~ /(?:[^0-9\.]|\A)#{Regexp.escape(version)}\z/ }&.
355
- name
356
- end
357
-
358
- def listing_tags
359
- return [] unless listing_upload_pack
360
-
361
- tags_for_upload_pack(listing_upload_pack)
362
- rescue GitDependenciesNotReachable
363
- []
364
- end
365
-
366
- def listing_upload_pack
367
- return unless listing_source_url
368
-
369
- @listing_upload_pack ||= fetch_upload_pack_for(listing_source_url)
370
- end
371
-
372
- def ignore_reqs
373
- ignored_versions.map { |req| requirement_class.new(req.split(",")) }
374
- end
375
-
376
- def wants_prerelease?
377
- return false unless dependency_source_details&.fetch(:ref, nil)
378
- return false unless pinned_ref_looks_like_version?
379
-
380
- version = dependency_source_details.fetch(:ref).match(VERSION_REGEX).
381
- named_captures.fetch("version")
382
- version_class.new(version).prerelease?
383
- end
384
-
385
- def tag_included_in_ignore_reqs?(tag)
386
- version = tag.name.match(VERSION_REGEX).named_captures.fetch("version")
387
- ignore_reqs.any? { |r| r.satisfied_by?(version_class.new(version)) }
388
- end
389
-
390
- def tag_is_prerelease?(tag)
391
- version = tag.name.match(VERSION_REGEX).named_captures.fetch("version")
392
- version_class.new(version).prerelease?
393
- end
394
-
395
- def version_class
396
- return @version_class if @version_class
397
-
398
- Utils.version_class_for_package_manager(dependency.package_manager)
399
- end
400
-
401
- def requirement_class
402
- return @requirement_class if @requirement_class
403
-
404
- Utils.requirement_class_for_package_manager(dependency.package_manager)
405
- end
406
-
407
- def sha_for_update_pack_line(line)
408
- line.split(" ").first.chars.last(40).join
409
- end
410
- end
411
- end
412
- # rubocop:enable Metrics/ClassLength