dependabot-bundler 0.95.5 → 0.95.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. metadata +4 -38
  3. data/helpers/Makefile +0 -9
  4. data/helpers/build +0 -26
  5. data/lib/dependabot/bundler.rb +0 -27
  6. data/lib/dependabot/bundler/file_fetcher.rb +0 -216
  7. data/lib/dependabot/bundler/file_fetcher/child_gemfile_finder.rb +0 -68
  8. data/lib/dependabot/bundler/file_fetcher/gemspec_finder.rb +0 -96
  9. data/lib/dependabot/bundler/file_fetcher/path_gemspec_finder.rb +0 -112
  10. data/lib/dependabot/bundler/file_fetcher/require_relative_finder.rb +0 -65
  11. data/lib/dependabot/bundler/file_parser.rb +0 -297
  12. data/lib/dependabot/bundler/file_parser/file_preparer.rb +0 -84
  13. data/lib/dependabot/bundler/file_parser/gemfile_checker.rb +0 -46
  14. data/lib/dependabot/bundler/file_updater.rb +0 -125
  15. data/lib/dependabot/bundler/file_updater/gemfile_updater.rb +0 -114
  16. data/lib/dependabot/bundler/file_updater/gemspec_dependency_name_finder.rb +0 -50
  17. data/lib/dependabot/bundler/file_updater/gemspec_sanitizer.rb +0 -298
  18. data/lib/dependabot/bundler/file_updater/gemspec_updater.rb +0 -62
  19. data/lib/dependabot/bundler/file_updater/git_pin_replacer.rb +0 -78
  20. data/lib/dependabot/bundler/file_updater/git_source_remover.rb +0 -100
  21. data/lib/dependabot/bundler/file_updater/lockfile_updater.rb +0 -387
  22. data/lib/dependabot/bundler/file_updater/requirement_replacer.rb +0 -221
  23. data/lib/dependabot/bundler/metadata_finder.rb +0 -204
  24. data/lib/dependabot/bundler/requirement.rb +0 -29
  25. data/lib/dependabot/bundler/update_checker.rb +0 -334
  26. data/lib/dependabot/bundler/update_checker/file_preparer.rb +0 -279
  27. data/lib/dependabot/bundler/update_checker/force_updater.rb +0 -259
  28. data/lib/dependabot/bundler/update_checker/latest_version_finder.rb +0 -165
  29. data/lib/dependabot/bundler/update_checker/requirements_updater.rb +0 -281
  30. data/lib/dependabot/bundler/update_checker/ruby_requirement_setter.rb +0 -113
  31. data/lib/dependabot/bundler/update_checker/shared_bundler_helpers.rb +0 -244
  32. data/lib/dependabot/bundler/update_checker/version_resolver.rb +0 -272
  33. data/lib/dependabot/bundler/version.rb +0 -13
  34. data/lib/dependabot/monkey_patches/bundler/definition_bundler_version_patch.rb +0 -15
  35. data/lib/dependabot/monkey_patches/bundler/definition_ruby_version_patch.rb +0 -14
  36. data/lib/dependabot/monkey_patches/bundler/git_source_patch.rb +0 -27
@@ -1,259 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/monkey_patches/bundler/definition_ruby_version_patch"
4
- require "dependabot/monkey_patches/bundler/definition_bundler_version_patch"
5
- require "dependabot/monkey_patches/bundler/git_source_patch"
6
-
7
- require "dependabot/bundler/update_checker"
8
- require "dependabot/bundler/update_checker/requirements_updater"
9
- require "dependabot/bundler/file_updater/lockfile_updater"
10
- require "dependabot/bundler/file_parser"
11
- require "dependabot/shared_helpers"
12
- require "dependabot/errors"
13
-
14
- module Dependabot
15
- module Bundler
16
- class UpdateChecker
17
- class ForceUpdater
18
- def initialize(dependency:, dependency_files:, credentials:,
19
- target_version:, requirements_update_strategy:)
20
- @dependency = dependency
21
- @dependency_files = dependency_files
22
- @credentials = credentials
23
- @target_version = target_version
24
- @requirements_update_strategy = requirements_update_strategy
25
- end
26
-
27
- def updated_dependencies
28
- @updated_dependencies ||= force_update
29
- end
30
-
31
- private
32
-
33
- attr_reader :dependency, :dependency_files, :credentials,
34
- :target_version, :requirements_update_strategy
35
-
36
- def force_update
37
- in_a_temporary_bundler_context do
38
- other_updates = []
39
-
40
- begin
41
- definition = build_definition(other_updates: other_updates)
42
- definition.resolve_remotely!
43
- specs = definition.resolve
44
- dependencies_from([dependency] + other_updates, specs)
45
- rescue ::Bundler::VersionConflict => error
46
- # TODO: Not sure this won't unlock way too many things...
47
- new_dependencies_to_unlock =
48
- new_dependencies_to_unlock_from(
49
- error: error,
50
- already_unlocked: other_updates
51
- )
52
-
53
- raise if new_dependencies_to_unlock.none?
54
-
55
- other_updates += new_dependencies_to_unlock
56
- retry
57
- end
58
- end
59
- rescue SharedHelpers::ChildProcessFailed => error
60
- raise_unresolvable_error(error)
61
- end
62
-
63
- #########################
64
- # Bundler context setup #
65
- #########################
66
-
67
- def in_a_temporary_bundler_context
68
- SharedHelpers.in_a_temporary_directory do
69
- write_temporary_dependency_files
70
-
71
- SharedHelpers.in_a_forked_process do
72
- # Remove installed gems from the default Rubygems index
73
- ::Gem::Specification.all = []
74
-
75
- # Set auth details
76
- relevant_credentials.each do |cred|
77
- token = cred["token"] ||
78
- "#{cred['username']}:#{cred['password']}"
79
-
80
- ::Bundler.settings.set_command_option(
81
- cred.fetch("host"),
82
- token.gsub("@", "%40F").gsub("?", "%3F")
83
- )
84
- end
85
-
86
- # Only allow upgrades. Othewise it's unlikely that this
87
- # resolution will be found by the FileUpdater
88
- ::Bundler.settings.set_command_option(
89
- "only_update_to_newer_versions",
90
- true
91
- )
92
-
93
- yield
94
- end
95
- end
96
- end
97
-
98
- def new_dependencies_to_unlock_from(error:, already_unlocked:)
99
- potentials_deps =
100
- error.cause.conflicts.values.
101
- flat_map(&:requirement_trees).
102
- reject do |tree|
103
- next true unless tree.last.requirement.specific?
104
- next false unless tree.last.name == dependency.name
105
-
106
- tree.last.requirement.satisfied_by?(
107
- Gem::Version.new(target_version)
108
- )
109
- end.map(&:first)
110
-
111
- potentials_deps.
112
- reject { |dep| already_unlocked.map(&:name).include?(dep.name) }.
113
- reject { |dep| [dependency.name, "ruby\0"].include?(dep.name) }.
114
- uniq
115
- end
116
-
117
- def raise_unresolvable_error(error)
118
- msg = error.error_class + " with message: " + error.error_message
119
- raise Dependabot::DependencyFileNotResolvable, msg
120
- end
121
-
122
- def build_definition(other_updates:)
123
- gems_to_unlock = other_updates.map(&:name) + [dependency.name]
124
- definition = ::Bundler::Definition.build(
125
- gemfile.name,
126
- lockfile&.name,
127
- gems: gems_to_unlock + subdependencies,
128
- lock_shared_dependencies: true
129
- )
130
-
131
- # Remove the Gemfile / gemspec requirements on the gems we're
132
- # unlocking (i.e., completely unlock them)
133
- gems_to_unlock.each do |gem_name|
134
- unlock_gem(definition: definition, gem_name: gem_name)
135
- end
136
-
137
- # Set the requirement for the gem we're forcing an update of
138
- new_req = Gem::Requirement.create("= #{target_version}")
139
- definition.dependencies.
140
- find { |d| d.name == dependency.name }.
141
- instance_variable_set(:@requirement, new_req)
142
-
143
- definition
144
- end
145
-
146
- def subdependencies
147
- # If there's no lockfile we don't need to worry about
148
- # subdependencies
149
- return [] unless lockfile
150
-
151
- all_deps = ::Bundler::LockfileParser.new(sanitized_lockfile_body).
152
- specs.map(&:name).map(&:to_s)
153
- top_level = ::Bundler::Definition.
154
- build(gemfile.name, lockfile.name, {}).
155
- dependencies.map(&:name).map(&:to_s)
156
-
157
- all_deps - top_level
158
- end
159
-
160
- def unlock_gem(definition:, gem_name:)
161
- dep = definition.dependencies.find { |d| d.name == gem_name }
162
- version = definition.locked_gems.specs.
163
- find { |d| d.name == gem_name }.version
164
-
165
- dep&.instance_variable_set(
166
- :@requirement,
167
- Gem::Requirement.create(">= #{version}")
168
- )
169
- end
170
-
171
- def original_dependencies
172
- @original_dependencies ||=
173
- FileParser.new(
174
- dependency_files: dependency_files,
175
- credentials: credentials,
176
- source: nil
177
- ).parse
178
- end
179
-
180
- def dependencies_from(updated_deps, specs)
181
- # You might think we'd want to remove dependencies whose version
182
- # hadn't changed from this array. We don't. We still need to unlock
183
- # them to get Bundler to resolve, because unlocking them is what
184
- # updates their subdependencies.
185
- #
186
- # This is kind of a bug in Bundler, and we should try to fix it,
187
- # but resolving it won't necessarily be easy.
188
- updated_deps.map do |dep|
189
- original_dep =
190
- original_dependencies.find { |d| d.name == dep.name }
191
- spec = specs.find { |d| d.name == dep.name }
192
-
193
- next if spec.version.to_s == original_dep.version
194
-
195
- build_dependency(original_dep, spec)
196
- end.compact
197
- end
198
-
199
- def build_dependency(original_dep, updated_spec)
200
- Dependency.new(
201
- name: updated_spec.name,
202
- version: updated_spec.version.to_s,
203
- requirements:
204
- RequirementsUpdater.new(
205
- requirements: original_dep.requirements,
206
- update_strategy: requirements_update_strategy,
207
- updated_source: source_for(original_dep),
208
- latest_version: updated_spec.version.to_s,
209
- latest_resolvable_version: updated_spec.version.to_s
210
- ).updated_requirements,
211
- previous_version: original_dep.version,
212
- previous_requirements: original_dep.requirements,
213
- package_manager: original_dep.package_manager
214
- )
215
- end
216
-
217
- def source_for(dependency)
218
- dependency.requirements.
219
- find { |r| r.fetch(:source) }&.
220
- fetch(:source)
221
- end
222
-
223
- def gemfile
224
- dependency_files.find { |f| f.name == "Gemfile" } ||
225
- dependency_files.find { |f| f.name == "gems.rb" }
226
- end
227
-
228
- def lockfile
229
- dependency_files.find { |f| f.name == "Gemfile.lock" } ||
230
- dependency_files.find { |f| f.name == "gems.locked" }
231
- end
232
-
233
- def sanitized_lockfile_body
234
- re = FileUpdater::LockfileUpdater::LOCKFILE_ENDING
235
- lockfile.content.gsub(re, "")
236
- end
237
-
238
- def write_temporary_dependency_files
239
- dependency_files.each do |file|
240
- path = file.name
241
- FileUtils.mkdir_p(Pathname.new(path).dirname)
242
- File.write(path, file.content)
243
- end
244
-
245
- File.write(lockfile.name, sanitized_lockfile_body) if lockfile
246
- end
247
-
248
- def relevant_credentials
249
- credentials.select do |cred|
250
- next true if cred["type"] == "git_source"
251
- next true if cred["type"] == "rubygems_server"
252
-
253
- false
254
- end
255
- end
256
- end
257
- end
258
- end
259
- end
@@ -1,165 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/monkey_patches/bundler/definition_ruby_version_patch"
4
- require "dependabot/monkey_patches/bundler/definition_bundler_version_patch"
5
- require "dependabot/monkey_patches/bundler/git_source_patch"
6
-
7
- require "excon"
8
-
9
- require "dependabot/bundler/update_checker"
10
- require "dependabot/bundler/requirement"
11
- require "dependabot/shared_helpers"
12
- require "dependabot/errors"
13
-
14
- module Dependabot
15
- module Bundler
16
- class UpdateChecker
17
- class LatestVersionFinder
18
- require_relative "shared_bundler_helpers"
19
- include SharedBundlerHelpers
20
-
21
- def initialize(dependency:, dependency_files:, credentials:,
22
- ignored_versions:)
23
- @dependency = dependency
24
- @dependency_files = dependency_files
25
- @credentials = credentials
26
- @ignored_versions = ignored_versions
27
- end
28
-
29
- def latest_version_details
30
- @latest_version_details ||= fetch_latest_version_details
31
- end
32
-
33
- private
34
-
35
- attr_reader :dependency, :dependency_files, :credentials,
36
- :ignored_versions
37
-
38
- def fetch_latest_version_details
39
- return latest_rubygems_version_details if dependency.name == "bundler"
40
-
41
- case dependency_source
42
- when NilClass then latest_rubygems_version_details
43
- when ::Bundler::Source::Rubygems
44
- if dependency_source.remotes.none? ||
45
- dependency_source.remotes.first.to_s == "https://rubygems.org/"
46
- latest_rubygems_version_details
47
- else
48
- latest_private_version_details
49
- end
50
- when ::Bundler::Source::Git then latest_git_version_details
51
- end
52
- end
53
-
54
- def latest_rubygems_version_details
55
- response = Excon.get(
56
- "https://rubygems.org/api/v1/versions/#{dependency.name}.json",
57
- idempotent: true,
58
- **SharedHelpers.excon_defaults
59
- )
60
-
61
- relevant_versions =
62
- JSON.parse(response.body).
63
- reject do |d|
64
- version = Gem::Version.new(d["number"])
65
- next true if version.prerelease? && !wants_prerelease?
66
- next true if ignore_reqs.any? { |r| r.satisfied_by?(version) }
67
-
68
- false
69
- end
70
-
71
- dep = relevant_versions.max_by { |d| Gem::Version.new(d["number"]) }
72
- return unless dep
73
-
74
- {
75
- version: Gem::Version.new(dep["number"]),
76
- sha: dep["sha"]
77
- }
78
- rescue JSON::ParserError, Excon::Error::Timeout
79
- nil
80
- end
81
-
82
- def latest_private_version_details
83
- in_a_temporary_bundler_context do
84
- spec =
85
- dependency_source.
86
- fetchers.flat_map do |fetcher|
87
- fetcher.
88
- specs_with_retry([dependency.name], dependency_source).
89
- search_all(dependency.name).
90
- reject { |s| s.version.prerelease? && !wants_prerelease? }.
91
- reject do |s|
92
- ignore_reqs.any? { |r| r.satisfied_by?(s.version) }
93
- end
94
- end.
95
- max_by(&:version)
96
- spec.nil? ? nil : { version: spec.version }
97
- end
98
- end
99
-
100
- def latest_git_version_details
101
- dependency_source_details =
102
- dependency.requirements.map { |r| r.fetch(:source) }.
103
- uniq.compact.first
104
-
105
- in_a_temporary_bundler_context do
106
- SharedHelpers.with_git_configured(credentials: credentials) do
107
- # Note: we don't set `ref`, as we want to unpin the dependency
108
- source = ::Bundler::Source::Git.new(
109
- "uri" => dependency_source_details[:url],
110
- "branch" => dependency_source_details[:branch],
111
- "name" => dependency.name,
112
- "submodules" => true
113
- )
114
-
115
- # Tell Bundler we're fine with fetching the source remotely
116
- source.instance_variable_set(:@allow_remote, true)
117
-
118
- spec = source.specs.first
119
- { version: spec.version, commit_sha: spec.source.revision }
120
- end
121
- end
122
- end
123
-
124
- def wants_prerelease?
125
- @wants_prerelease ||=
126
- begin
127
- current_version = dependency.version
128
- if current_version && Gem::Version.correct?(current_version) &&
129
- Gem::Version.new(current_version).prerelease?
130
- return true
131
- end
132
-
133
- dependency.requirements.any? do |req|
134
- req[:requirement].match?(/[a-z]/i)
135
- end
136
- end
137
- end
138
-
139
- def dependency_source
140
- return nil unless gemfile
141
-
142
- @dependency_source ||=
143
- in_a_temporary_bundler_context do
144
- definition = ::Bundler::Definition.build(gemfile.name, nil, {})
145
-
146
- specified_source =
147
- definition.dependencies.
148
- find { |dep| dep.name == dependency.name }&.source
149
-
150
- specified_source || definition.send(:sources).default_source
151
- end
152
- end
153
-
154
- def ignore_reqs
155
- ignored_versions.map { |req| Gem::Requirement.new(req.split(",")) }
156
- end
157
-
158
- def gemfile
159
- dependency_files.find { |f| f.name == "Gemfile" } ||
160
- dependency_files.find { |f| f.name == "gems.rb" }
161
- end
162
- end
163
- end
164
- end
165
- end
@@ -1,281 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/bundler/update_checker"
4
-
5
- module Dependabot
6
- module Bundler
7
- class UpdateChecker
8
- class RequirementsUpdater
9
- class UnfixableRequirement < StandardError; end
10
-
11
- ALLOWED_UPDATE_STRATEGIES =
12
- %i(bump_versions bump_versions_if_necessary).freeze
13
-
14
- def initialize(requirements:, update_strategy:, updated_source:,
15
- latest_version:, latest_resolvable_version:)
16
- @requirements = requirements
17
- @latest_version = Gem::Version.new(latest_version) if latest_version
18
- @updated_source = updated_source
19
- @update_strategy = update_strategy
20
-
21
- check_update_strategy
22
-
23
- return unless latest_resolvable_version
24
-
25
- @latest_resolvable_version =
26
- Gem::Version.new(latest_resolvable_version)
27
- end
28
-
29
- def updated_requirements
30
- requirements.map do |req|
31
- if req[:file].match?(/\.gemspec/)
32
- update_gemspec_requirement(req)
33
- else
34
- # If a requirement doesn't come from a gemspec, it must be from
35
- # a Gemfile.
36
- update_gemfile_requirement(req)
37
- end
38
- end
39
- end
40
-
41
- private
42
-
43
- attr_reader :requirements, :updated_source,
44
- :latest_version, :latest_resolvable_version,
45
- :update_strategy
46
-
47
- def check_update_strategy
48
- return if ALLOWED_UPDATE_STRATEGIES.include?(update_strategy)
49
-
50
- raise "Unknown update strategy: #{update_strategy}"
51
- end
52
-
53
- def update_gemfile_requirement(req)
54
- req = req.merge(source: updated_source)
55
- return req unless latest_resolvable_version
56
-
57
- case update_strategy
58
- when :bump_versions
59
- update_version_requirement(req)
60
- when :bump_versions_if_necessary
61
- update_version_requirement_if_needed(req)
62
- else raise "Unexpected update strategy: #{update_strategy}"
63
- end
64
- end
65
-
66
- def update_version_requirement_if_needed(req)
67
- return req if new_version_satisfies?(req)
68
-
69
- update_version_requirement(req)
70
- end
71
-
72
- def update_version_requirement(req)
73
- requirements =
74
- req[:requirement].split(",").map { |r| Gem::Requirement.new(r) }
75
-
76
- new_requirement =
77
- if requirements.any?(&:exact?) then latest_resolvable_version.to_s
78
- elsif requirements.any? { |r| r.to_s.start_with?("~>") }
79
- tw_req = requirements.find { |r| r.to_s.start_with?("~>") }
80
- update_twiddle_version(tw_req, latest_resolvable_version).to_s
81
- else
82
- update_gemfile_range(requirements).map(&:to_s).join(", ")
83
- end
84
-
85
- req.merge(requirement: new_requirement)
86
- end
87
-
88
- def new_version_satisfies?(req)
89
- original_req = Gem::Requirement.new(req[:requirement].split(","))
90
- original_req.satisfied_by?(latest_resolvable_version)
91
- end
92
-
93
- def update_gemfile_range(requirements)
94
- updated_requirements =
95
- requirements.flat_map do |r|
96
- next r if r.satisfied_by?(latest_resolvable_version)
97
-
98
- case op = r.requirements.first.first
99
- when "<", "<="
100
- [update_greatest_version(r, latest_resolvable_version)]
101
- when "!="
102
- []
103
- else
104
- raise "Unexpected operation for unsatisfied Gemfile "\
105
- "requirement: #{op}"
106
- end
107
- end
108
-
109
- binding_requirements(updated_requirements)
110
- end
111
-
112
- def at_same_precision(new_version, old_version)
113
- release_precision =
114
- old_version.to_s.split(".").select { |i| i.match?(/^\d+$/) }.count
115
- prerelease_precision =
116
- old_version.to_s.split(".").count - release_precision
117
-
118
- new_release =
119
- new_version.to_s.split(".").first(release_precision)
120
- new_prerelease =
121
- new_version.to_s.split(".").
122
- drop_while { |i| i.match?(/^\d+$/) }.
123
- first([prerelease_precision, 1].max)
124
-
125
- [*new_release, *new_prerelease].join(".")
126
- end
127
-
128
- # rubocop:disable Metrics/PerceivedComplexity
129
- def update_gemspec_requirement(req)
130
- return req unless latest_version && latest_resolvable_version
131
-
132
- requirements =
133
- req[:requirement].split(",").map { |r| Gem::Requirement.new(r) }
134
-
135
- return req if requirements.all? do |r|
136
- requirement_satisfied?(r, req[:groups])
137
- end
138
-
139
- updated_requirements =
140
- requirements.flat_map do |r|
141
- next r if requirement_satisfied?(r, req[:groups])
142
-
143
- if req[:groups] == ["development"] then bumped_requirements(r)
144
- else widened_requirements(r)
145
- end
146
- end
147
-
148
- updated_requirements = binding_requirements(updated_requirements)
149
- req.merge(requirement: updated_requirements.map(&:to_s).join(", "))
150
- rescue UnfixableRequirement
151
- req.merge(requirement: :unfixable)
152
- end
153
- # rubocop:enable Metrics/PerceivedComplexity
154
-
155
- def requirement_satisfied?(req, groups)
156
- if groups == ["development"]
157
- req.satisfied_by?(latest_resolvable_version)
158
- else
159
- req.satisfied_by?(latest_version)
160
- end
161
- end
162
-
163
- def binding_requirements(requirements)
164
- grouped_by_operator =
165
- requirements.group_by { |r| r.requirements.first.first }
166
-
167
- binding_reqs = grouped_by_operator.flat_map do |operator, reqs|
168
- case operator
169
- when "<", "<=" then reqs.min_by { |r| r.requirements.first.last }
170
- when ">", ">=" then reqs.max_by { |r| r.requirements.first.last }
171
- else requirements
172
- end
173
- end.uniq
174
-
175
- binding_reqs << Gem::Requirement.new if binding_reqs.empty?
176
- binding_reqs.sort_by { |r| r.requirements.first.last }
177
- end
178
-
179
- def widened_requirements(req)
180
- op, version = req.requirements.first
181
-
182
- case op
183
- when "=", nil
184
- if version < latest_resolvable_version
185
- [Gem::Requirement.new("#{op} #{latest_resolvable_version}")]
186
- else
187
- req
188
- end
189
- when "<", "<=" then [update_greatest_version(req, latest_version)]
190
- when "~>" then convert_twidle_to_range(req, latest_version)
191
- when "!=" then []
192
- when ">", ">=" then raise UnfixableRequirement
193
- else raise "Unexpected operation for requirement: #{op}"
194
- end
195
- end
196
-
197
- def bumped_requirements(req)
198
- op, version = req.requirements.first
199
-
200
- case op
201
- when "=", nil
202
- if version < latest_resolvable_version
203
- [Gem::Requirement.new("#{op} #{latest_resolvable_version}")]
204
- else
205
- req
206
- end
207
- when "~>"
208
- [update_twiddle_version(req, latest_resolvable_version)]
209
- when "<", "<=" then [update_greatest_version(req, latest_version)]
210
- when "!=" then []
211
- when ">", ">=" then raise UnfixableRequirement
212
- else raise "Unexpected operation for requirement: #{op}"
213
- end
214
- end
215
-
216
- # rubocop:disable Metrics/AbcSize
217
- def convert_twidle_to_range(requirement, version_to_be_permitted)
218
- version = requirement.requirements.first.last
219
- version = version.release if version.prerelease?
220
-
221
- index_to_update = [version.segments.count - 2, 0].max
222
-
223
- ub_segments = version_to_be_permitted.segments
224
- ub_segments << 0 while ub_segments.count <= index_to_update
225
- ub_segments = ub_segments[0..index_to_update]
226
- ub_segments[index_to_update] += 1
227
-
228
- lb_segments = version.segments
229
- lb_segments.pop while lb_segments.any? && lb_segments.last.zero?
230
-
231
- if lb_segments.none?
232
- return [Gem::Requirement.new("< #{ub_segments.join('.')}")]
233
- end
234
-
235
- # Ensure versions have the same length as each other (cosmetic)
236
- length = [lb_segments.count, ub_segments.count].max
237
- lb_segments.fill(0, lb_segments.count...length)
238
- ub_segments.fill(0, ub_segments.count...length)
239
-
240
- [
241
- Gem::Requirement.new(">= #{lb_segments.join('.')}"),
242
- Gem::Requirement.new("< #{ub_segments.join('.')}")
243
- ]
244
- end
245
- # rubocop:enable Metrics/AbcSize
246
-
247
- # Updates the version in a "~>" constraint to allow the given version
248
- def update_twiddle_version(requirement, version_to_be_permitted)
249
- old_version = requirement.requirements.first.last
250
- updated_v = at_same_precision(version_to_be_permitted, old_version)
251
- Gem::Requirement.new("~> #{updated_v}")
252
- end
253
-
254
- # Updates the version in a "<" or "<=" constraint to allow the given
255
- # version
256
- def update_greatest_version(requirement, version_to_be_permitted)
257
- if version_to_be_permitted.is_a?(String)
258
- version_to_be_permitted =
259
- Gem::Version.new(version_to_be_permitted)
260
- end
261
- op, version = requirement.requirements.first
262
- version = version.release if version.prerelease?
263
-
264
- index_to_update =
265
- version.segments.map.with_index { |seg, i| seg.zero? ? 0 : i }.max
266
-
267
- new_segments = version.segments.map.with_index do |_, index|
268
- if index < index_to_update
269
- version_to_be_permitted.segments[index]
270
- elsif index == index_to_update
271
- version_to_be_permitted.segments[index] + 1
272
- else 0
273
- end
274
- end
275
-
276
- Gem::Requirement.new("#{op} #{new_segments.join('.')}")
277
- end
278
- end
279
- end
280
- end
281
- end