dependabot-core 0.93.17 → 0.94.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/dependabot/dependency.rb +16 -21
  4. data/lib/dependabot/file_fetchers.rb +1 -5
  5. data/lib/dependabot/file_parsers.rb +1 -5
  6. data/lib/dependabot/file_updaters.rb +1 -5
  7. data/lib/dependabot/metadata_finders.rb +1 -5
  8. data/lib/dependabot/pull_request_creator/labeler.rb +26 -24
  9. data/lib/dependabot/update_checkers.rb +1 -5
  10. data/lib/dependabot/utils.rb +2 -12
  11. data/lib/dependabot/version.rb +1 -1
  12. metadata +1 -28
  13. data/lib/dependabot/file_fetchers/ruby/bundler.rb +0 -215
  14. data/lib/dependabot/file_fetchers/ruby/bundler/child_gemfile_finder.rb +0 -70
  15. data/lib/dependabot/file_fetchers/ruby/bundler/gemspec_finder.rb +0 -98
  16. data/lib/dependabot/file_fetchers/ruby/bundler/path_gemspec_finder.rb +0 -114
  17. data/lib/dependabot/file_fetchers/ruby/bundler/require_relative_finder.rb +0 -67
  18. data/lib/dependabot/file_parsers/ruby/bundler.rb +0 -294
  19. data/lib/dependabot/file_parsers/ruby/bundler/file_preparer.rb +0 -86
  20. data/lib/dependabot/file_parsers/ruby/bundler/gemfile_checker.rb +0 -48
  21. data/lib/dependabot/file_updaters/ruby/bundler.rb +0 -123
  22. data/lib/dependabot/file_updaters/ruby/bundler/gemfile_updater.rb +0 -116
  23. data/lib/dependabot/file_updaters/ruby/bundler/gemspec_dependency_name_finder.rb +0 -52
  24. data/lib/dependabot/file_updaters/ruby/bundler/gemspec_sanitizer.rb +0 -298
  25. data/lib/dependabot/file_updaters/ruby/bundler/gemspec_updater.rb +0 -64
  26. data/lib/dependabot/file_updaters/ruby/bundler/git_pin_replacer.rb +0 -80
  27. data/lib/dependabot/file_updaters/ruby/bundler/git_source_remover.rb +0 -102
  28. data/lib/dependabot/file_updaters/ruby/bundler/lockfile_updater.rb +0 -389
  29. data/lib/dependabot/file_updaters/ruby/bundler/requirement_replacer.rb +0 -223
  30. data/lib/dependabot/metadata_finders/ruby/bundler.rb +0 -202
  31. data/lib/dependabot/update_checkers/ruby/bundler.rb +0 -331
  32. data/lib/dependabot/update_checkers/ruby/bundler/file_preparer.rb +0 -281
  33. data/lib/dependabot/update_checkers/ruby/bundler/force_updater.rb +0 -261
  34. data/lib/dependabot/update_checkers/ruby/bundler/latest_version_finder.rb +0 -169
  35. data/lib/dependabot/update_checkers/ruby/bundler/requirements_updater.rb +0 -283
  36. data/lib/dependabot/update_checkers/ruby/bundler/ruby_requirement_setter.rb +0 -115
  37. data/lib/dependabot/update_checkers/ruby/bundler/shared_bundler_helpers.rb +0 -246
  38. data/lib/dependabot/update_checkers/ruby/bundler/version_resolver.rb +0 -272
  39. data/lib/dependabot/utils/ruby/requirement.rb +0 -26
@@ -1,223 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "parser/current"
4
- require "dependabot/file_updaters/ruby/bundler"
5
-
6
- module Dependabot
7
- module FileUpdaters
8
- module Ruby
9
- class Bundler
10
- class RequirementReplacer
11
- attr_reader :dependency, :file_type, :updated_requirement,
12
- :previous_requirement
13
-
14
- def initialize(dependency:, file_type:, updated_requirement:,
15
- previous_requirement: nil, insert_if_bare: false)
16
- @dependency = dependency
17
- @file_type = file_type
18
- @updated_requirement = updated_requirement
19
- @previous_requirement = previous_requirement
20
- @insert_if_bare = insert_if_bare
21
- end
22
-
23
- def rewrite(content)
24
- buffer = Parser::Source::Buffer.new("(gemfile_content)")
25
- buffer.source = content
26
- ast = Parser::CurrentRuby.new.parse(buffer)
27
-
28
- updated_content = Rewriter.new(
29
- dependency: dependency,
30
- file_type: file_type,
31
- updated_requirement: updated_requirement,
32
- insert_if_bare: insert_if_bare?
33
- ).rewrite(buffer, ast)
34
-
35
- update_comment_spacing_if_required(content, updated_content)
36
- end
37
-
38
- private
39
-
40
- def insert_if_bare?
41
- @insert_if_bare
42
- end
43
-
44
- def update_comment_spacing_if_required(content, updated_content)
45
- return updated_content unless previous_requirement
46
-
47
- return updated_content if updated_content == content
48
- return updated_content if length_change.zero?
49
-
50
- updated_lines = updated_content.lines
51
- updated_line_index =
52
- updated_lines.length.
53
- times.find { |i| content.lines[i] != updated_content.lines[i] }
54
- updated_line = updated_lines[updated_line_index]
55
-
56
- updated_line =
57
- if length_change.positive?
58
- updated_line.sub(/(?<=\s)\s{#{length_change}}#/, "#")
59
- elsif length_change.negative?
60
- updated_line.sub(/(?<=\s{2})#/, " " * length_change.abs + "#")
61
- end
62
-
63
- updated_lines[updated_line_index] = updated_line
64
- updated_lines.join
65
- end
66
-
67
- def length_change
68
- unless previous_requirement.start_with?("=")
69
- return updated_requirement.length - previous_requirement.length
70
- end
71
-
72
- updated_requirement.length -
73
- previous_requirement.gsub(/^=/, "").strip.length
74
- end
75
-
76
- class Rewriter < Parser::TreeRewriter
77
- # TODO: Ideally we wouldn't have to ignore all of these, but
78
- # implementing each one will be tricky.
79
- SKIPPED_TYPES = %i(send lvar dstr begin if splat const).freeze
80
-
81
- def initialize(dependency:, file_type:, updated_requirement:,
82
- insert_if_bare:)
83
- @dependency = dependency
84
- @file_type = file_type
85
- @updated_requirement = updated_requirement
86
- @insert_if_bare = insert_if_bare
87
-
88
- return if %i(gemfile gemspec).include?(file_type)
89
-
90
- raise "File type must be :gemfile or :gemspec. Got #{file_type}."
91
- end
92
-
93
- def on_send(node)
94
- return unless declares_targeted_gem?(node)
95
-
96
- req_nodes = node.children[3..-1]
97
- req_nodes = req_nodes.reject { |child| child.type == :hash }
98
-
99
- return if req_nodes.none? && !insert_if_bare?
100
- return if req_nodes.any? { |n| SKIPPED_TYPES.include?(n.type) }
101
-
102
- quote_characters = extract_quote_characters_from(req_nodes)
103
- space_after_specifier = space_after_specifier?(req_nodes)
104
- use_equality_operator = use_equality_operator?(req_nodes)
105
-
106
- new_req = new_requirement_string(
107
- quote_characters: quote_characters,
108
- space_after_specifier: space_after_specifier,
109
- use_equality_operator: use_equality_operator
110
- )
111
- if req_nodes.any?
112
- replace(range_for(req_nodes), new_req)
113
- else
114
- insert_after(range_for(node.children[2..2]), ", #{new_req}")
115
- end
116
- end
117
-
118
- private
119
-
120
- attr_reader :dependency, :file_type, :updated_requirement
121
-
122
- def insert_if_bare?
123
- @insert_if_bare
124
- end
125
-
126
- def declaration_methods
127
- return %i(gem) if file_type == :gemfile
128
-
129
- %i(add_dependency add_runtime_dependency
130
- add_development_dependency)
131
- end
132
-
133
- def declares_targeted_gem?(node)
134
- return false unless declaration_methods.include?(node.children[1])
135
-
136
- node.children[2].children.first == dependency.name
137
- end
138
-
139
- def extract_quote_characters_from(requirement_nodes)
140
- return ['"', '"'] if requirement_nodes.none?
141
-
142
- case requirement_nodes.first.type
143
- when :str, :dstr
144
- [
145
- requirement_nodes.first.loc.begin.source,
146
- requirement_nodes.first.loc.end.source
147
- ]
148
- else
149
- [
150
- requirement_nodes.first.children.first.loc.begin.source,
151
- requirement_nodes.first.children.first.loc.end.source
152
- ]
153
- end
154
- end
155
-
156
- def space_after_specifier?(requirement_nodes)
157
- return true if requirement_nodes.none?
158
-
159
- req_string =
160
- case requirement_nodes.first.type
161
- when :str, :dstr
162
- requirement_nodes.first.loc.expression.source
163
- else
164
- requirement_nodes.first.children.first.loc.expression.source
165
- end
166
-
167
- ops = Gem::Requirement::OPS.keys
168
- return true if ops.none? { |op| req_string.include?(op) }
169
-
170
- req_string.include?(" ")
171
- end
172
-
173
- def use_equality_operator?(requirement_nodes)
174
- return true if requirement_nodes.none?
175
-
176
- req_string =
177
- case requirement_nodes.first.type
178
- when :str, :dstr
179
- requirement_nodes.first.loc.expression.source
180
- else
181
- requirement_nodes.first.children.first.loc.expression.source
182
- end
183
-
184
- req_string.match?(/(?<![<>])=/)
185
- end
186
-
187
- def new_requirement_string(quote_characters:,
188
- space_after_specifier:,
189
- use_equality_operator:)
190
- open_quote, close_quote = quote_characters
191
- new_requirement_string =
192
- updated_requirement.split(",").
193
- map do |r|
194
- req_string = serialized_req(r, use_equality_operator)
195
- %(#{open_quote}#{req_string}#{close_quote})
196
- end.join(", ")
197
-
198
- new_requirement_string.delete!(" ") unless space_after_specifier
199
- new_requirement_string
200
- end
201
-
202
- def serialized_req(req, use_equality_operator)
203
- tmp_req = req
204
-
205
- # Gem::Requirement serializes exact matches as a string starting
206
- # with `=`. We may need to remove that equality operator if it
207
- # wasn't used originally.
208
- unless use_equality_operator
209
- tmp_req = tmp_req.gsub(/(?<![<>])=/, "")
210
- end
211
-
212
- tmp_req.strip
213
- end
214
-
215
- def range_for(nodes)
216
- nodes.first.loc.begin.begin.join(nodes.last.loc.expression)
217
- end
218
- end
219
- end
220
- end
221
- end
222
- end
223
- end
@@ -1,202 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "excon"
4
- require "dependabot/metadata_finders/base"
5
-
6
- module Dependabot
7
- module MetadataFinders
8
- module Ruby
9
- class Bundler < Dependabot::MetadataFinders::Base
10
- SOURCE_KEYS = %w(
11
- source_code_uri
12
- homepage_uri
13
- wiki_uri
14
- bug_tracker_uri
15
- documentation_uri
16
- changelog_uri
17
- mailing_list_uri
18
- download_uri
19
- ).freeze
20
-
21
- def homepage_url
22
- return super unless %w(default rubygems).include?(new_source_type)
23
- return super unless rubygems_api_response["homepage_uri"]
24
-
25
- rubygems_api_response["homepage_uri"]
26
- end
27
-
28
- private
29
-
30
- def look_up_source
31
- case new_source_type
32
- when "git" then find_source_from_git_url
33
- when "default", "rubygems" then find_source_from_rubygems
34
- else raise "Unexpected source type: #{new_source_type}"
35
- end
36
- end
37
-
38
- def new_source_type
39
- sources =
40
- dependency.requirements.map { |r| r.fetch(:source) }.uniq.compact
41
-
42
- return "default" if sources.empty?
43
- raise "Multiple sources! #{sources.join(', ')}" if sources.count > 1
44
-
45
- sources.first[:type] || sources.first.fetch("type")
46
- end
47
-
48
- def find_source_from_rubygems
49
- api_source = find_source_from_rubygems_api_response
50
- return api_source if api_source || new_source_type == "default"
51
-
52
- find_source_from_gemspec_download
53
- end
54
-
55
- def find_source_from_rubygems_api_response
56
- source_url = rubygems_api_response.
57
- values_at(*SOURCE_KEYS).
58
- compact.
59
- find { |url| Source.from_url(url) }
60
-
61
- Source.from_url(source_url)
62
- end
63
-
64
- def find_source_from_git_url
65
- info = dependency.requirements.map { |r| r[:source] }.compact.first
66
-
67
- url = info[:url] || info.fetch("url")
68
- Source.from_url(url)
69
- end
70
-
71
- def find_source_from_gemspec_download
72
- github_urls = []
73
- return unless rubygems_marshalled_gemspec_response
74
-
75
- rubygems_marshalled_gemspec_response.scan(Source::SOURCE_REGEX) do
76
- github_urls << Regexp.last_match.to_s
77
- end
78
-
79
- source_url = github_urls.find do |url|
80
- repo = Source.from_url(url).repo
81
- repo.downcase.end_with?(dependency.name)
82
- end
83
- return unless source_url
84
-
85
- Source.from_url(source_url)
86
- end
87
-
88
- # Note: This response MUST NOT be unmarshalled
89
- # (as calling Marshal.load is unsafe)
90
- def rubygems_marshalled_gemspec_response
91
- if defined?(@rubygems_marshalled_gemspec_response)
92
- return @rubygems_marshalled_gemspec_response
93
- end
94
-
95
- gemspec_uri =
96
- "#{registry_url}quick/Marshal.4.8/"\
97
- "#{dependency.name}-#{dependency.version}.gemspec.rz"
98
-
99
- response =
100
- Excon.get(
101
- gemspec_uri,
102
- headers: registry_auth_headers,
103
- idempotent: true,
104
- **SharedHelpers.excon_defaults
105
- )
106
-
107
- if response.status >= 400
108
- return @rubygems_marshalled_gemspec_response = nil
109
- end
110
-
111
- @rubygems_marshalled_gemspec_response =
112
- Zlib::Inflate.inflate(response.body)
113
- rescue Zlib::DataError
114
- @rubygems_marshalled_gemspec_response = nil
115
- end
116
-
117
- def rubygems_api_response
118
- return @rubygems_api_response if defined?(@rubygems_api_response)
119
-
120
- response =
121
- Excon.get(
122
- "#{registry_url}api/v1/gems/#{dependency.name}.json",
123
- headers: registry_auth_headers,
124
- idempotent: true,
125
- **SharedHelpers.excon_defaults
126
- )
127
- return @rubygems_api_response = {} if response.status >= 400
128
-
129
- response_body = response.body
130
- response_body = augment_private_response_if_appropriate(response_body)
131
-
132
- @rubygems_api_response = JSON.parse(response_body)
133
- append_slash_to_source_code_uri(@rubygems_api_response)
134
- rescue JSON::ParserError, Excon::Error::Timeout
135
- @rubygems_api_response = {}
136
- end
137
-
138
- def append_slash_to_source_code_uri(listing)
139
- # We have to do this so that `Source.from_url(...)` doesn't prune the
140
- # last line off of the directory.
141
- return listing unless listing&.fetch("source_code_uri", nil)
142
- return listing if listing.fetch("source_code_uri").end_with?("/")
143
-
144
- listing["source_code_uri"] = listing["source_code_uri"] + "/"
145
- listing
146
- end
147
-
148
- def augment_private_response_if_appropriate(response_body)
149
- return response_body if new_source_type == "default"
150
-
151
- parsed_body = JSON.parse(response_body)
152
- return response_body if (SOURCE_KEYS - parsed_body.keys).none?
153
-
154
- digest = parsed_body.values_at("version", "authors", "info").hash
155
-
156
- source_url = parsed_body.
157
- values_at(*SOURCE_KEYS).
158
- compact.
159
- find { |url| Source.from_url(url) }
160
- return response_body if source_url
161
-
162
- rubygems_response =
163
- Excon.get(
164
- "https://rubygems.org/api/v1/gems/#{dependency.name}.json",
165
- idempotent: true,
166
- **SharedHelpers.excon_defaults
167
- )
168
- parsed_rubygems_body = JSON.parse(rubygems_response.body)
169
- rubygems_digest =
170
- parsed_rubygems_body.values_at("version", "authors", "info").hash
171
-
172
- digest == rubygems_digest ? rubygems_response.body : response_body
173
- rescue JSON::ParserError, Excon::Error::Socket, Excon::Error::Timeout
174
- response_body
175
- end
176
-
177
- def registry_url
178
- return "https://rubygems.org/" if new_source_type == "default"
179
-
180
- info = dependency.requirements.map { |r| r[:source] }.compact.first
181
- info[:url] || info.fetch("url")
182
- end
183
-
184
- def registry_auth_headers
185
- return {} unless new_source_type == "rubygems"
186
-
187
- token =
188
- credentials.
189
- select { |cred| cred["type"] == "rubygems_server" }.
190
- find { |cred| registry_url.include?(cred["host"]) }&.
191
- fetch("token")
192
-
193
- return {} unless token
194
-
195
- token += ":" unless token.include?(":")
196
- encoded_token = Base64.encode64(token).delete("\n")
197
- { "Authorization" => "Basic #{encoded_token}" }
198
- end
199
- end
200
- end
201
- end
202
- end
@@ -1,331 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/update_checkers/base"
4
- require "dependabot/file_updaters/ruby/bundler/requirement_replacer"
5
- require "dependabot/git_commit_checker"
6
-
7
- module Dependabot
8
- module UpdateCheckers
9
- module Ruby
10
- class Bundler < Dependabot::UpdateCheckers::Base
11
- require_relative "bundler/force_updater"
12
- require_relative "bundler/file_preparer"
13
- require_relative "bundler/requirements_updater"
14
- require_relative "bundler/version_resolver"
15
- require_relative "bundler/latest_version_finder"
16
-
17
- def latest_version
18
- return latest_version_for_git_dependency if git_dependency?
19
-
20
- latest_version_details&.fetch(:version)
21
- end
22
-
23
- def latest_resolvable_version
24
- return latest_resolvable_version_for_git_dependency if git_dependency?
25
-
26
- latest_resolvable_version_details&.fetch(:version)
27
- end
28
-
29
- def latest_resolvable_version_with_no_unlock
30
- current_ver = dependency.version
31
- return current_ver if git_dependency? && git_commit_checker.pinned?
32
-
33
- @latest_resolvable_version_detail_with_no_unlock ||=
34
- version_resolver(
35
- remove_git_source: false,
36
- unlock_requirement: false
37
- ).latest_resolvable_version_details
38
-
39
- if git_dependency?
40
- @latest_resolvable_version_detail_with_no_unlock&.fetch(:commit_sha)
41
- else
42
- @latest_resolvable_version_detail_with_no_unlock&.fetch(:version)
43
- end
44
- end
45
-
46
- def updated_requirements
47
- RequirementsUpdater.new(
48
- requirements: dependency.requirements,
49
- update_strategy: requirements_update_strategy,
50
- updated_source: updated_source,
51
- latest_version: latest_version_details&.fetch(:version)&.to_s,
52
- latest_resolvable_version:
53
- latest_resolvable_version_details&.fetch(:version)&.to_s
54
- ).updated_requirements
55
- end
56
-
57
- def requirements_unlocked_or_can_be?
58
- dependency.requirements.
59
- reject { |r| r[:requirement].nil? }.
60
- all? do |req|
61
- requirement = requirement_class.new(req[:requirement])
62
- next true if requirement.satisfied_by?(Gem::Version.new("100000"))
63
-
64
- file = dependency_files.find { |f| f.name == req.fetch(:file) }
65
- updated = FileUpdaters::Ruby::Bundler::RequirementReplacer.new(
66
- dependency: dependency,
67
- file_type: file.name.end_with?("gemspec") ? :gemspec : :gemfile,
68
- updated_requirement: "whatever"
69
- ).rewrite(file.content)
70
-
71
- updated != file.content
72
- end
73
- end
74
-
75
- def requirements_update_strategy
76
- # If passed in as an option (in the base class) honour that option
77
- if @requirements_update_strategy
78
- return @requirements_update_strategy.to_sym
79
- end
80
-
81
- # Otherwise, widen ranges for libraries and bump versions for apps
82
- dependency.version.nil? ? :bump_versions_if_necessary : :bump_versions
83
- end
84
-
85
- private
86
-
87
- def latest_version_resolvable_with_full_unlock?
88
- return false unless latest_version
89
-
90
- updated_dependencies = force_updater.updated_dependencies
91
-
92
- updated_dependencies.none? do |dep|
93
- old_version = dep.previous_version
94
- next unless Gem::Version.correct?(old_version)
95
- next if Gem::Version.new(old_version).prerelease?
96
-
97
- Gem::Version.new(dep.version).prerelease?
98
- end
99
- rescue Dependabot::DependencyFileNotResolvable
100
- false
101
- end
102
-
103
- def updated_dependencies_after_full_unlock
104
- force_updater.updated_dependencies
105
- end
106
-
107
- def git_dependency?
108
- git_commit_checker.git_dependency?
109
- end
110
-
111
- def latest_version_details(remove_git_source: false)
112
- @latest_version_details ||= {}
113
- @latest_version_details[remove_git_source] ||=
114
- latest_version_finder(remove_git_source: remove_git_source).
115
- latest_version_details
116
- end
117
-
118
- def latest_resolvable_version_details(remove_git_source: false)
119
- @latest_resolvable_version_details ||= {}
120
- @latest_resolvable_version_details[remove_git_source] ||=
121
- version_resolver(remove_git_source: remove_git_source).
122
- latest_resolvable_version_details
123
- end
124
-
125
- def latest_version_for_git_dependency
126
- latest_release =
127
- latest_version_details(remove_git_source: true)&.
128
- fetch(:version)
129
-
130
- # If there's been a release that includes the current pinned ref or
131
- # that the current branch is behind, we switch to that release.
132
- return latest_release if git_branch_or_ref_in_release?(latest_release)
133
-
134
- # Otherwise, if the gem isn't pinned, the latest version is just the
135
- # latest commit for the specified branch.
136
- unless git_commit_checker.pinned?
137
- return git_commit_checker.head_commit_for_current_branch
138
- end
139
-
140
- # If the dependency is pinned to a tag that looks like a version then
141
- # we want to update that tag. The latest version will then be the SHA
142
- # of the latest tag that looks like a version.
143
- if git_commit_checker.pinned_ref_looks_like_version?
144
- latest_tag = git_commit_checker.local_tag_for_latest_version
145
- return latest_tag&.fetch(:tag_sha) || dependency.version
146
- end
147
-
148
- # If the dependency is pinned to a tag that doesn't look like a
149
- # version then there's nothing we can do.
150
- dependency.version
151
- end
152
-
153
- def latest_resolvable_version_for_git_dependency
154
- latest_release = latest_resolvable_version_without_git_source
155
-
156
- # If there's a resolvable release that includes the current pinned
157
- # ref or that the current branch is behind, we switch to that release.
158
- return latest_release if git_branch_or_ref_in_release?(latest_release)
159
-
160
- # Otherwise, if the gem isn't pinned, the latest version is just the
161
- # latest commit for the specified branch.
162
- unless git_commit_checker.pinned?
163
- return latest_resolvable_commit_with_unchanged_git_source
164
- end
165
-
166
- # If the dependency is pinned to a tag that looks like a version then
167
- # we want to update that tag. The latest version will then be the SHA
168
- # of the latest tag that looks like a version.
169
- if git_commit_checker.pinned_ref_looks_like_version? &&
170
- latest_git_tag_is_resolvable?
171
- new_tag = git_commit_checker.local_tag_for_latest_version
172
- return new_tag.fetch(:tag_sha)
173
- end
174
-
175
- # If the dependency is pinned to a tag that doesn't look like a
176
- # version then there's nothing we can do.
177
- dependency.version
178
- end
179
-
180
- def latest_resolvable_version_without_git_source
181
- return nil unless latest_version.is_a?(Gem::Version)
182
-
183
- latest_resolvable_version_details(remove_git_source: true)&.
184
- fetch(:version)
185
- rescue Dependabot::DependencyFileNotResolvable
186
- nil
187
- end
188
-
189
- def latest_resolvable_commit_with_unchanged_git_source
190
- details = latest_resolvable_version_details(remove_git_source: false)
191
-
192
- # If this dependency has a git version in the Gemfile.lock but not in
193
- # the Gemfile (i.e., because they're out-of-sync) we might not get a
194
- # commit_sha back from Bundler. In that case, return `nil`.
195
- return unless details.key?(:commit_sha)
196
-
197
- details.fetch(:commit_sha)
198
- rescue Dependabot::DependencyFileNotResolvable
199
- nil
200
- end
201
-
202
- def latest_git_tag_is_resolvable?
203
- return @git_tag_resolvable if @latest_git_tag_is_resolvable_checked
204
-
205
- @latest_git_tag_is_resolvable_checked = true
206
-
207
- return false if git_commit_checker.local_tag_for_latest_version.nil?
208
-
209
- replacement_tag = git_commit_checker.local_tag_for_latest_version
210
-
211
- VersionResolver.new(
212
- dependency: dependency,
213
- unprepared_dependency_files: dependency_files,
214
- credentials: credentials,
215
- ignored_versions: ignored_versions,
216
- replacement_git_pin: replacement_tag.fetch(:tag)
217
- ).latest_resolvable_version_details
218
-
219
- @git_tag_resolvable = true
220
- rescue Dependabot::DependencyFileNotResolvable
221
- @git_tag_resolvable = false
222
- end
223
-
224
- def git_branch_or_ref_in_release?(release)
225
- return false unless release
226
-
227
- git_commit_checker.branch_or_ref_in_release?(release)
228
- end
229
-
230
- def updated_source
231
- # Never need to update source, unless a git_dependency
232
- return dependency_source_details unless git_dependency?
233
-
234
- # Source becomes `nil` if switching to default rubygems
235
- return nil if should_switch_source_from_git_to_rubygems?
236
-
237
- # Update the git tag if updating a pinned version
238
- if git_commit_checker.pinned_ref_looks_like_version? &&
239
- latest_git_tag_is_resolvable?
240
- new_tag = git_commit_checker.local_tag_for_latest_version
241
- return dependency_source_details.merge(ref: new_tag.fetch(:tag))
242
- end
243
-
244
- # Otherwise return the original source
245
- dependency_source_details
246
- end
247
-
248
- def dependency_source_details
249
- sources =
250
- dependency.requirements.map { |r| r.fetch(:source) }.uniq.compact
251
-
252
- raise "Multiple sources! #{sources.join(', ')}" if sources.count > 1
253
-
254
- sources.first
255
- end
256
-
257
- def should_switch_source_from_git_to_rubygems?
258
- return false unless git_dependency?
259
- return false if latest_resolvable_version_for_git_dependency.nil?
260
-
261
- Gem::Version.correct?(latest_resolvable_version_for_git_dependency)
262
- end
263
-
264
- def force_updater
265
- @force_updater ||=
266
- ForceUpdater.new(
267
- dependency: dependency,
268
- dependency_files: dependency_files,
269
- credentials: credentials,
270
- target_version: latest_version,
271
- requirements_update_strategy: requirements_update_strategy
272
- )
273
- end
274
-
275
- def git_commit_checker
276
- @git_commit_checker ||=
277
- GitCommitChecker.new(
278
- dependency: dependency,
279
- credentials: credentials
280
- )
281
- end
282
-
283
- def version_resolver(remove_git_source:, unlock_requirement: true)
284
- @version_resolver ||= {}
285
- @version_resolver[remove_git_source] ||= {}
286
- @version_resolver[remove_git_source][unlock_requirement] ||=
287
- begin
288
- VersionResolver.new(
289
- dependency: dependency,
290
- unprepared_dependency_files: dependency_files,
291
- credentials: credentials,
292
- ignored_versions: ignored_versions,
293
- remove_git_source: remove_git_source,
294
- unlock_requirement: unlock_requirement,
295
- latest_allowable_version: latest_version
296
- )
297
- end
298
- end
299
-
300
- def latest_version_finder(remove_git_source:)
301
- @latest_version_finder ||= {}
302
- @latest_version_finder[remove_git_source] ||=
303
- begin
304
- prepared_dependency_files = prepared_dependency_files(
305
- remove_git_source: remove_git_source,
306
- unlock_requirement: true
307
- )
308
-
309
- LatestVersionFinder.new(
310
- dependency: dependency,
311
- dependency_files: prepared_dependency_files,
312
- credentials: credentials,
313
- ignored_versions: ignored_versions
314
- )
315
- end
316
- end
317
-
318
- def prepared_dependency_files(remove_git_source:, unlock_requirement:,
319
- latest_allowable_version: nil)
320
- FilePreparer.new(
321
- dependency: dependency,
322
- dependency_files: dependency_files,
323
- remove_git_source: remove_git_source,
324
- unlock_requirement: unlock_requirement,
325
- latest_allowable_version: latest_allowable_version
326
- ).prepared_dependency_files
327
- end
328
- end
329
- end
330
- end
331
- end