dependabot-bundler 0.95.5 → 0.95.6

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 (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