dependabot-core 0.88.3 → 0.89.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/helpers/test/run.rb +3 -0
- data/lib/dependabot/file_fetchers.rb +0 -2
- data/lib/dependabot/file_parsers.rb +0 -2
- data/lib/dependabot/file_updaters.rb +0 -2
- data/lib/dependabot/file_updaters/go/dep/lockfile_updater.rb +11 -8
- data/lib/dependabot/metadata_finders.rb +0 -2
- data/lib/dependabot/shared_helpers.rb +47 -24
- data/lib/dependabot/update_checkers.rb +0 -2
- data/lib/dependabot/update_checkers/go/dep/version_resolver.rb +11 -7
- data/lib/dependabot/utils.rb +0 -4
- data/lib/dependabot/version.rb +1 -1
- metadata +2 -25
- data/helpers/php/.php_cs +0 -34
- data/helpers/php/bin/run.php +0 -84
- data/helpers/php/composer.json +0 -14
- data/helpers/php/composer.lock +0 -1528
- data/helpers/php/composer.phar +0 -0
- data/helpers/php/setup.sh +0 -4
- data/helpers/php/src/DependabotInstallationManager.php +0 -61
- data/helpers/php/src/DependabotPluginManager.php +0 -23
- data/helpers/php/src/ExceptionIO.php +0 -25
- data/helpers/php/src/Hasher.php +0 -21
- data/helpers/php/src/UpdateChecker.php +0 -123
- data/helpers/php/src/Updater.php +0 -97
- data/lib/dependabot/file_fetchers/php/composer.rb +0 -131
- data/lib/dependabot/file_parsers/php/composer.rb +0 -177
- data/lib/dependabot/file_updaters/php/composer.rb +0 -78
- data/lib/dependabot/file_updaters/php/composer/lockfile_updater.rb +0 -269
- data/lib/dependabot/file_updaters/php/composer/manifest_updater.rb +0 -70
- data/lib/dependabot/metadata_finders/php/composer.rb +0 -66
- data/lib/dependabot/update_checkers/php/composer.rb +0 -175
- data/lib/dependabot/update_checkers/php/composer/requirements_updater.rb +0 -258
- data/lib/dependabot/update_checkers/php/composer/version_resolver.rb +0 -216
- data/lib/dependabot/utils/php/requirement.rb +0 -97
- data/lib/dependabot/utils/php/version.rb +0 -24
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "dependabot/file_updaters/php/composer"
|
4
|
-
|
5
|
-
module Dependabot
|
6
|
-
module FileUpdaters
|
7
|
-
module Php
|
8
|
-
class Composer
|
9
|
-
class ManifestUpdater
|
10
|
-
def initialize(dependencies:, manifest:)
|
11
|
-
@dependencies = dependencies
|
12
|
-
@manifest = manifest
|
13
|
-
end
|
14
|
-
|
15
|
-
def updated_manifest_content
|
16
|
-
dependencies.reduce(manifest.content.dup) do |content, dep|
|
17
|
-
updated_content = content
|
18
|
-
updated_requirements(dep).each do |new_req|
|
19
|
-
old_req = old_requirement(dep, new_req).fetch(:requirement)
|
20
|
-
updated_req = new_req.fetch(:requirement)
|
21
|
-
|
22
|
-
regex =
|
23
|
-
/
|
24
|
-
"#{Regexp.escape(dep.name)}"\s*:\s*
|
25
|
-
"#{Regexp.escape(old_req)}"
|
26
|
-
/x
|
27
|
-
|
28
|
-
updated_content = content.gsub(regex) do |declaration|
|
29
|
-
declaration.gsub(%("#{old_req}"), %("#{updated_req}"))
|
30
|
-
end
|
31
|
-
|
32
|
-
if content == updated_content
|
33
|
-
raise "Expected content to change!"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
updated_content
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
attr_reader :dependencies, :manifest
|
44
|
-
|
45
|
-
def new_requirements(dependency)
|
46
|
-
dependency.requirements.select { |r| r[:file] == manifest.name }
|
47
|
-
end
|
48
|
-
|
49
|
-
def old_requirement(dependency, new_requirement)
|
50
|
-
dependency.previous_requirements.
|
51
|
-
select { |r| r[:file] == manifest.name }.
|
52
|
-
find { |r| r[:groups] == new_requirement[:groups] }
|
53
|
-
end
|
54
|
-
|
55
|
-
def updated_requirements(dependency)
|
56
|
-
new_requirements(dependency).
|
57
|
-
reject { |r| dependency.previous_requirements.include?(r) }
|
58
|
-
end
|
59
|
-
|
60
|
-
def requirement_changed?(file, dependency)
|
61
|
-
changed_requirements =
|
62
|
-
dependency.requirements - dependency.previous_requirements
|
63
|
-
|
64
|
-
changed_requirements.any? { |f| f[:file] == file.name }
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "excon"
|
4
|
-
require "dependabot/metadata_finders/base"
|
5
|
-
require "dependabot/shared_helpers"
|
6
|
-
require "dependabot/utils"
|
7
|
-
|
8
|
-
module Dependabot
|
9
|
-
module MetadataFinders
|
10
|
-
module Php
|
11
|
-
class Composer < Dependabot::MetadataFinders::Base
|
12
|
-
private
|
13
|
-
|
14
|
-
def look_up_source
|
15
|
-
source_from_dependency || look_up_source_from_packagist
|
16
|
-
end
|
17
|
-
|
18
|
-
def source_from_dependency
|
19
|
-
source_url =
|
20
|
-
dependency.requirements.
|
21
|
-
map { |r| r.fetch(:source) }.compact.
|
22
|
-
first&.fetch(:url, nil)
|
23
|
-
|
24
|
-
Source.from_url(source_url)
|
25
|
-
end
|
26
|
-
|
27
|
-
def look_up_source_from_packagist
|
28
|
-
return nil if packagist_listing&.fetch("packages", nil) == []
|
29
|
-
unless packagist_listing&.dig("packages", dependency.name.downcase)
|
30
|
-
return nil
|
31
|
-
end
|
32
|
-
|
33
|
-
version_listings =
|
34
|
-
packagist_listing["packages"][dependency.name.downcase].
|
35
|
-
select { |version, _| Utils::Php::Version.correct?(version) }.
|
36
|
-
sort_by { |version, _| Utils::Php::Version.new(version) }.
|
37
|
-
map { |_, listing| listing }.
|
38
|
-
reverse
|
39
|
-
|
40
|
-
potential_source_urls =
|
41
|
-
version_listings.
|
42
|
-
flat_map { |info| [info["homepage"], info.dig("source", "url")] }.
|
43
|
-
compact
|
44
|
-
|
45
|
-
source_url = potential_source_urls.find { |url| Source.from_url(url) }
|
46
|
-
|
47
|
-
Source.from_url(source_url)
|
48
|
-
end
|
49
|
-
|
50
|
-
def packagist_listing
|
51
|
-
return @packagist_listing unless @packagist_listing.nil?
|
52
|
-
|
53
|
-
response = Excon.get(
|
54
|
-
"https://packagist.org/p/#{dependency.name.downcase}.json",
|
55
|
-
idempotent: true,
|
56
|
-
**SharedHelpers.excon_defaults
|
57
|
-
)
|
58
|
-
|
59
|
-
return nil unless response.status == 200
|
60
|
-
|
61
|
-
@packagist_listing = JSON.parse(response.body)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,175 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "excon"
|
4
|
-
require "dependabot/update_checkers/base"
|
5
|
-
require "dependabot/shared_helpers"
|
6
|
-
require "dependabot/errors"
|
7
|
-
|
8
|
-
require "json"
|
9
|
-
|
10
|
-
module Dependabot
|
11
|
-
module UpdateCheckers
|
12
|
-
module Php
|
13
|
-
class Composer < Dependabot::UpdateCheckers::Base
|
14
|
-
require_relative "composer/requirements_updater"
|
15
|
-
require_relative "composer/version_resolver"
|
16
|
-
|
17
|
-
def latest_version
|
18
|
-
return nil if path_dependency?
|
19
|
-
|
20
|
-
# Fall back to latest_resolvable_version if no listings found
|
21
|
-
latest_version_from_registry || latest_resolvable_version
|
22
|
-
end
|
23
|
-
|
24
|
-
def latest_resolvable_version
|
25
|
-
return nil if path_dependency?
|
26
|
-
|
27
|
-
@latest_resolvable_version ||=
|
28
|
-
VersionResolver.new(
|
29
|
-
credentials: credentials,
|
30
|
-
dependency: dependency,
|
31
|
-
dependency_files: dependency_files,
|
32
|
-
latest_allowable_version: latest_version_from_registry,
|
33
|
-
requirements_to_unlock: :own
|
34
|
-
).latest_resolvable_version
|
35
|
-
end
|
36
|
-
|
37
|
-
def latest_resolvable_version_with_no_unlock
|
38
|
-
return nil if path_dependency?
|
39
|
-
|
40
|
-
@latest_resolvable_version_with_no_unlock ||=
|
41
|
-
VersionResolver.new(
|
42
|
-
credentials: credentials,
|
43
|
-
dependency: dependency,
|
44
|
-
dependency_files: dependency_files,
|
45
|
-
latest_allowable_version: latest_version_from_registry,
|
46
|
-
requirements_to_unlock: :none
|
47
|
-
).latest_resolvable_version
|
48
|
-
end
|
49
|
-
|
50
|
-
def updated_requirements
|
51
|
-
RequirementsUpdater.new(
|
52
|
-
requirements: dependency.requirements,
|
53
|
-
latest_version: latest_version&.to_s,
|
54
|
-
latest_resolvable_version: latest_resolvable_version&.to_s,
|
55
|
-
update_strategy: requirements_update_strategy
|
56
|
-
).updated_requirements
|
57
|
-
end
|
58
|
-
|
59
|
-
def requirements_update_strategy
|
60
|
-
# If passed in as an option (in the base class) honour that option
|
61
|
-
if @requirements_update_strategy
|
62
|
-
return @requirements_update_strategy.to_sym
|
63
|
-
end
|
64
|
-
|
65
|
-
# Otherwise, widen ranges for libraries and bump versions for apps
|
66
|
-
library? ? :widen_ranges : :bump_versions_if_necessary
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
def latest_version_resolvable_with_full_unlock?
|
72
|
-
# Full unlock checks aren't implemented for Composer (yet)
|
73
|
-
false
|
74
|
-
end
|
75
|
-
|
76
|
-
def latest_version_from_registry
|
77
|
-
versions =
|
78
|
-
registry_versions.
|
79
|
-
select { |version| version_class.correct?(version.gsub(/^v/, "")) }.
|
80
|
-
map { |version| version_class.new(version.gsub(/^v/, "")) }
|
81
|
-
|
82
|
-
versions.reject!(&:prerelease?) unless wants_prerelease?
|
83
|
-
versions.reject! { |v| ignore_reqs.any? { |r| r.satisfied_by?(v) } }
|
84
|
-
versions.max
|
85
|
-
end
|
86
|
-
|
87
|
-
def wants_prerelease?
|
88
|
-
current_version = dependency.version
|
89
|
-
if current_version && version_class.new(current_version).prerelease?
|
90
|
-
return true
|
91
|
-
end
|
92
|
-
|
93
|
-
dependency.requirements.any? do |req|
|
94
|
-
req[:requirement].match?(/\d-[A-Za-z]/)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def updated_dependencies_after_full_unlock
|
99
|
-
raise NotImplementedError
|
100
|
-
end
|
101
|
-
|
102
|
-
def path_dependency?
|
103
|
-
dependency.requirements.any? { |r| r.dig(:source, :type) == "path" }
|
104
|
-
end
|
105
|
-
|
106
|
-
def composer_file
|
107
|
-
composer_file =
|
108
|
-
dependency_files.find { |f| f.name == "composer.json" }
|
109
|
-
raise "No composer.json!" unless composer_file
|
110
|
-
|
111
|
-
composer_file
|
112
|
-
end
|
113
|
-
|
114
|
-
def lockfile
|
115
|
-
dependency_files.find { |f| f.name == "composer.lock" }
|
116
|
-
end
|
117
|
-
|
118
|
-
def registry_versions
|
119
|
-
return @registry_versions unless @registry_versions.nil?
|
120
|
-
|
121
|
-
repositories =
|
122
|
-
JSON.parse(composer_file.content).
|
123
|
-
fetch("repositories", []).
|
124
|
-
select { |r| r.is_a?(Hash) }
|
125
|
-
|
126
|
-
urls = repositories.
|
127
|
-
select { |h| h["type"] == "composer" }.
|
128
|
-
map { |h| h["url"] }.compact.
|
129
|
-
map { |url| url.gsub(%r{\/$}, "") + "/packages.json" }
|
130
|
-
|
131
|
-
unless repositories.any? { |rep| rep["packagist.org"] == false }
|
132
|
-
urls << "https://packagist.org/p/#{dependency.name.downcase}.json"
|
133
|
-
end
|
134
|
-
|
135
|
-
@registry_versions = []
|
136
|
-
urls.each do |url|
|
137
|
-
@registry_versions += fetch_registry_versions_from_url(url)
|
138
|
-
end
|
139
|
-
@registry_versions.uniq
|
140
|
-
end
|
141
|
-
|
142
|
-
def fetch_registry_versions_from_url(url)
|
143
|
-
cred = registry_credentials.find { |c| url.include?(c["registry"]) }
|
144
|
-
|
145
|
-
response = Excon.get(
|
146
|
-
url,
|
147
|
-
idempotent: true,
|
148
|
-
user: cred&.fetch("username", nil),
|
149
|
-
password: cred&.fetch("password", nil),
|
150
|
-
**SharedHelpers.excon_defaults
|
151
|
-
)
|
152
|
-
|
153
|
-
return [] unless response.status == 200
|
154
|
-
|
155
|
-
listing = JSON.parse(response.body)
|
156
|
-
return [] if listing.nil?
|
157
|
-
return [] if listing.fetch("packages", []) == []
|
158
|
-
return [] unless listing.dig("packages", dependency.name.downcase)
|
159
|
-
|
160
|
-
listing.dig("packages", dependency.name.downcase).keys
|
161
|
-
rescue Excon::Error::Socket, Excon::Error::Timeout
|
162
|
-
[]
|
163
|
-
end
|
164
|
-
|
165
|
-
def library?
|
166
|
-
JSON.parse(composer_file.content)["type"] == "library"
|
167
|
-
end
|
168
|
-
|
169
|
-
def registry_credentials
|
170
|
-
credentials.select { |cred| cred["type"] == "composer_repository" }
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
@@ -1,258 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
################################################################################
|
4
|
-
# For more details on Composer version constraints, see: #
|
5
|
-
# https://getcomposer.org/doc/articles/versions.md#writing-version-constraints #
|
6
|
-
################################################################################
|
7
|
-
|
8
|
-
require "dependabot/update_checkers/php/composer"
|
9
|
-
require "dependabot/utils/php/version"
|
10
|
-
require "dependabot/utils/php/requirement"
|
11
|
-
|
12
|
-
module Dependabot
|
13
|
-
module UpdateCheckers
|
14
|
-
module Php
|
15
|
-
class Composer
|
16
|
-
class RequirementsUpdater
|
17
|
-
ALIAS_REGEX = /[a-z0-9\-_\.]*\sas\s+/.freeze
|
18
|
-
VERSION_REGEX =
|
19
|
-
/(?:#{ALIAS_REGEX})?[0-9]+(?:\.[a-zA-Z0-9*\-]+)*/.freeze
|
20
|
-
AND_SEPARATOR =
|
21
|
-
/(?<=[a-zA-Z0-9*])(?<!\sas)[\s,]+(?![\s,]*[|-]|as)/.freeze
|
22
|
-
OR_SEPARATOR = /(?<=[a-zA-Z0-9*])[\s,]*\|\|?\s*/.freeze
|
23
|
-
SEPARATOR = /(?:#{AND_SEPARATOR})|(?:#{OR_SEPARATOR})/.freeze
|
24
|
-
ALLOWED_UPDATE_STRATEGIES =
|
25
|
-
%i(widen_ranges bump_versions bump_versions_if_necessary).freeze
|
26
|
-
|
27
|
-
def initialize(requirements:, update_strategy:,
|
28
|
-
latest_version:, latest_resolvable_version:)
|
29
|
-
@requirements = requirements
|
30
|
-
@update_strategy = update_strategy
|
31
|
-
|
32
|
-
check_update_strategy
|
33
|
-
|
34
|
-
if latest_version
|
35
|
-
@latest_version = version_class.new(latest_version)
|
36
|
-
end
|
37
|
-
|
38
|
-
return unless latest_resolvable_version
|
39
|
-
|
40
|
-
@latest_resolvable_version =
|
41
|
-
version_class.new(latest_resolvable_version)
|
42
|
-
end
|
43
|
-
|
44
|
-
def updated_requirements
|
45
|
-
return requirements unless latest_resolvable_version
|
46
|
-
|
47
|
-
requirements.map { |req| updated_requirement(req) }
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
attr_reader :requirements, :update_strategy,
|
53
|
-
:latest_version, :latest_resolvable_version
|
54
|
-
|
55
|
-
def check_update_strategy
|
56
|
-
return if ALLOWED_UPDATE_STRATEGIES.include?(update_strategy)
|
57
|
-
|
58
|
-
raise "Unknown update strategy: #{update_strategy}"
|
59
|
-
end
|
60
|
-
|
61
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
62
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
63
|
-
def updated_requirement(req)
|
64
|
-
req_string = req[:requirement].strip
|
65
|
-
or_string_reqs = req_string.split(OR_SEPARATOR)
|
66
|
-
or_separator = req_string.match(OR_SEPARATOR)&.to_s || " || "
|
67
|
-
numeric_or_string_reqs = or_string_reqs.
|
68
|
-
reject { |r| r.start_with?("dev-") }
|
69
|
-
branch_or_string_reqs = or_string_reqs.
|
70
|
-
select { |r| r.start_with?("dev-") }
|
71
|
-
|
72
|
-
return req unless req_string.match?(/\d/)
|
73
|
-
return req if numeric_or_string_reqs.none?
|
74
|
-
return updated_alias(req) if req_string.match?(ALIAS_REGEX)
|
75
|
-
return req if req_satisfied_by_latest_resolvable?(req_string) &&
|
76
|
-
update_strategy != :bump_versions
|
77
|
-
|
78
|
-
new_req =
|
79
|
-
case update_strategy
|
80
|
-
when :widen_ranges
|
81
|
-
widen_requirement(req, or_separator)
|
82
|
-
when :bump_versions, :bump_versions_if_necessary
|
83
|
-
update_requirement_version(req, or_separator)
|
84
|
-
end
|
85
|
-
|
86
|
-
new_req_string =
|
87
|
-
[new_req[:requirement], *branch_or_string_reqs].join(or_separator)
|
88
|
-
new_req.merge(requirement: new_req_string)
|
89
|
-
end
|
90
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
91
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
92
|
-
|
93
|
-
def updated_alias(req)
|
94
|
-
req_string = req[:requirement]
|
95
|
-
real_version = req_string.split(/\sas\s/).first.strip
|
96
|
-
|
97
|
-
# If the version we're aliasing isn't a version then we don't know
|
98
|
-
# how to update it, so we just return the existing requirement.
|
99
|
-
return req unless version_class.correct?(real_version)
|
100
|
-
|
101
|
-
new_version_string = latest_resolvable_version.to_s
|
102
|
-
new_req = req_string.sub(real_version, new_version_string)
|
103
|
-
req.merge(requirement: new_req)
|
104
|
-
end
|
105
|
-
|
106
|
-
def widen_requirement(req, or_separator)
|
107
|
-
current_requirement = req[:requirement]
|
108
|
-
reqs = current_requirement.strip.split(SEPARATOR).map(&:strip)
|
109
|
-
|
110
|
-
updated_requirement =
|
111
|
-
if reqs.any? { |r| r.start_with?("^") }
|
112
|
-
update_caret_requirement(current_requirement, or_separator)
|
113
|
-
elsif reqs.any? { |r| r.start_with?("~") }
|
114
|
-
update_tilda_requirement(current_requirement, or_separator)
|
115
|
-
elsif reqs.any? { |r| r.include?("*") }
|
116
|
-
update_wildcard_requirement(current_requirement, or_separator)
|
117
|
-
elsif reqs.any? { |r| r.match?(/<|(\s+-\s+)/) }
|
118
|
-
update_range_requirement(current_requirement, or_separator)
|
119
|
-
else
|
120
|
-
update_version_string(current_requirement)
|
121
|
-
end
|
122
|
-
|
123
|
-
req.merge(requirement: updated_requirement)
|
124
|
-
end
|
125
|
-
|
126
|
-
def update_requirement_version(req, or_separator)
|
127
|
-
current_requirement = req[:requirement]
|
128
|
-
reqs = current_requirement.strip.split(SEPARATOR).map(&:strip)
|
129
|
-
|
130
|
-
updated_requirement =
|
131
|
-
if reqs.count > 1
|
132
|
-
"^#{latest_resolvable_version}"
|
133
|
-
elsif reqs.any? { |r| r.match?(/<|(\s+-\s+)/) }
|
134
|
-
update_range_requirement(current_requirement, or_separator)
|
135
|
-
elsif reqs.any? { |r| r.match?(/>[^=]/) }
|
136
|
-
current_requirement
|
137
|
-
else
|
138
|
-
update_version_string(current_requirement)
|
139
|
-
end
|
140
|
-
|
141
|
-
req.merge(requirement: updated_requirement)
|
142
|
-
end
|
143
|
-
|
144
|
-
def req_satisfied_by_latest_resolvable?(requirement_string)
|
145
|
-
ruby_requirements(requirement_string).
|
146
|
-
any? { |r| r.satisfied_by?(latest_resolvable_version) }
|
147
|
-
end
|
148
|
-
|
149
|
-
def update_version_string(req_string)
|
150
|
-
req_string.
|
151
|
-
sub(VERSION_REGEX) do |old_version|
|
152
|
-
unless req_string.match?(/[~*\^]/)
|
153
|
-
next latest_resolvable_version.to_s
|
154
|
-
end
|
155
|
-
|
156
|
-
old_parts = old_version.split(".")
|
157
|
-
new_parts = latest_resolvable_version.to_s.split(".").
|
158
|
-
first(old_parts.count)
|
159
|
-
new_parts.map.with_index do |part, i|
|
160
|
-
old_parts[i] == "*" ? "*" : part
|
161
|
-
end.join(".")
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def ruby_requirements(requirement_string)
|
166
|
-
Utils::Php::Requirement.requirements_array(requirement_string)
|
167
|
-
end
|
168
|
-
|
169
|
-
def update_caret_requirement(req_string, or_separator)
|
170
|
-
caret_requirements =
|
171
|
-
req_string.split(SEPARATOR).select { |r| r.start_with?("^") }
|
172
|
-
version_parts = latest_resolvable_version.segments
|
173
|
-
|
174
|
-
min_existing_precision =
|
175
|
-
caret_requirements.map { |r| r.split(".").count }.min
|
176
|
-
first_non_zero_index =
|
177
|
-
version_parts.count.times.find { |i| version_parts[i] != 0 }
|
178
|
-
|
179
|
-
precision = [min_existing_precision, first_non_zero_index + 1].max
|
180
|
-
version = version_parts.first(precision).map.with_index do |part, i|
|
181
|
-
i <= first_non_zero_index ? part : 0
|
182
|
-
end.join(".")
|
183
|
-
|
184
|
-
req_string + "#{or_separator}^#{version}"
|
185
|
-
end
|
186
|
-
|
187
|
-
def update_tilda_requirement(req_string, or_separator)
|
188
|
-
tilda_requirements =
|
189
|
-
req_string.split(SEPARATOR).select { |r| r.start_with?("~") }
|
190
|
-
precision = tilda_requirements.map { |r| r.split(".").count }.min
|
191
|
-
|
192
|
-
version_parts = latest_resolvable_version.segments.first(precision)
|
193
|
-
version_parts[-1] = 0
|
194
|
-
version = version_parts.join(".")
|
195
|
-
|
196
|
-
req_string + "#{or_separator}~#{version}"
|
197
|
-
end
|
198
|
-
|
199
|
-
def update_wildcard_requirement(req_string, or_separator)
|
200
|
-
wildcard_requirements =
|
201
|
-
req_string.split(SEPARATOR).select { |r| r.include?("*") }
|
202
|
-
precision = wildcard_requirements.map do |r|
|
203
|
-
r.split(".").reject { |s| s == "*" }.count
|
204
|
-
end.min
|
205
|
-
wildcard_count = wildcard_requirements.map do |r|
|
206
|
-
r.split(".").select { |s| s == "*" }.count
|
207
|
-
end.min
|
208
|
-
|
209
|
-
version_parts = latest_resolvable_version.segments.first(precision)
|
210
|
-
version = version_parts.join(".")
|
211
|
-
|
212
|
-
req_string + "#{or_separator}#{version}#{'.*' * wildcard_count}"
|
213
|
-
end
|
214
|
-
|
215
|
-
def update_range_requirement(req_string, or_separator)
|
216
|
-
range_requirements =
|
217
|
-
req_string.split(SEPARATOR).select { |r| r.match?(/<|(\s+-\s+)/) }
|
218
|
-
|
219
|
-
if range_requirements.count == 1
|
220
|
-
range_requirement = range_requirements.first
|
221
|
-
versions = range_requirement.scan(VERSION_REGEX)
|
222
|
-
upper_bound = versions.map { |v| version_class.new(v) }.max
|
223
|
-
new_upper_bound = update_greatest_version(
|
224
|
-
upper_bound,
|
225
|
-
latest_resolvable_version
|
226
|
-
)
|
227
|
-
|
228
|
-
req_string.sub(upper_bound.to_s, new_upper_bound.to_s)
|
229
|
-
else
|
230
|
-
req_string + "#{or_separator}^#{latest_resolvable_version}"
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
def update_greatest_version(old_version, version_to_be_permitted)
|
235
|
-
version = version_class.new(old_version)
|
236
|
-
version = version.release if version.prerelease?
|
237
|
-
|
238
|
-
index_to_update =
|
239
|
-
version.segments.map.with_index { |seg, i| seg.zero? ? 0 : i }.max
|
240
|
-
|
241
|
-
version.segments.map.with_index do |_, index|
|
242
|
-
if index < index_to_update
|
243
|
-
version_to_be_permitted.segments[index]
|
244
|
-
elsif index == index_to_update
|
245
|
-
version_to_be_permitted.segments[index] + 1
|
246
|
-
else 0
|
247
|
-
end
|
248
|
-
end.join(".")
|
249
|
-
end
|
250
|
-
|
251
|
-
def version_class
|
252
|
-
Utils::Php::Version
|
253
|
-
end
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|