dependabot-composer 0.398.0 → 0.400.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.
- checksums.yaml +4 -4
- data/helpers/v2/composer.lock +22 -22
- data/lib/dependabot/composer/document_value_parser.rb +41 -0
- data/lib/dependabot/composer/file_fetcher/path_dependency_builder.rb +13 -17
- data/lib/dependabot/composer/file_fetcher.rb +21 -41
- data/lib/dependabot/composer/file_parser.rb +32 -35
- data/lib/dependabot/composer/file_updater/lockfile_updater.rb +14 -3
- data/lib/dependabot/composer/helpers.rb +17 -16
- data/lib/dependabot/composer/lockfile_document.rb +180 -0
- data/lib/dependabot/composer/manifest_document.rb +145 -0
- data/lib/dependabot/composer/package/package_details_fetcher.rb +18 -74
- data/lib/dependabot/composer/package/registry_package.rb +146 -0
- data/lib/dependabot/composer/update_checker/version_resolver.rb +13 -4
- metadata +8 -4
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "json"
|
|
5
|
+
require "time"
|
|
6
|
+
require "uri"
|
|
7
|
+
require "sorbet-runtime"
|
|
8
|
+
require "dependabot/errors"
|
|
9
|
+
require "dependabot/composer/document_value_parser"
|
|
10
|
+
|
|
11
|
+
module Dependabot
|
|
12
|
+
module Composer
|
|
13
|
+
module Package
|
|
14
|
+
class RegistryPackage < T::ImmutableStruct
|
|
15
|
+
extend T::Sig
|
|
16
|
+
|
|
17
|
+
class Release < T::ImmutableStruct
|
|
18
|
+
const :version_string, T.nilable(String)
|
|
19
|
+
const :released_at, T.nilable(Time)
|
|
20
|
+
const :url, T.nilable(String)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
const :releases, T::Array[Release]
|
|
24
|
+
|
|
25
|
+
sig { params(content: String, package_name: String, source: String).returns(RegistryPackage) }
|
|
26
|
+
def self.from_json(content, package_name:, source:)
|
|
27
|
+
name = package_name.downcase
|
|
28
|
+
context = "Registry '#{source_label(source)}' package '#{name}'"
|
|
29
|
+
value = T.cast(JSON.parse(content), Object)
|
|
30
|
+
return new(releases: []) if value.nil? || value == []
|
|
31
|
+
|
|
32
|
+
fields = DocumentValueParser.object_hash(value, context)
|
|
33
|
+
entries = version_entries(fields["packages"], name, context)
|
|
34
|
+
return new(releases: []) if entries.empty?
|
|
35
|
+
|
|
36
|
+
new(releases: parse_releases(entries, minified: minified?(fields["minified"], context), context: context))
|
|
37
|
+
rescue JSON::ParserError
|
|
38
|
+
raise DependencyFileNotResolvable.new("#{context} must contain valid JSON"), cause: nil
|
|
39
|
+
rescue TypeError => e
|
|
40
|
+
raise DependencyFileNotResolvable.new(e.message), cause: nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
sig { params(source: String).returns(String) }
|
|
44
|
+
def self.source_label(source)
|
|
45
|
+
uri = URI.parse(source)
|
|
46
|
+
uri.userinfo = nil
|
|
47
|
+
uri.query = nil
|
|
48
|
+
uri.fragment = nil
|
|
49
|
+
String(uri)
|
|
50
|
+
end
|
|
51
|
+
private_class_method :source_label
|
|
52
|
+
|
|
53
|
+
sig { params(value: Object, name: String, context: String).returns(T::Array[Object]) }
|
|
54
|
+
def self.version_entries(value, name, context)
|
|
55
|
+
return [] if value.nil? || value == []
|
|
56
|
+
|
|
57
|
+
packages = DocumentValueParser.object_hash(value, "#{context} packages")
|
|
58
|
+
versions = packages[name]
|
|
59
|
+
case versions
|
|
60
|
+
when nil then []
|
|
61
|
+
when Hash then DocumentValueParser.object_hash(versions, "#{context} versions").values
|
|
62
|
+
when Array then versions.map { |entry| T.cast(entry, Object) }
|
|
63
|
+
else raise TypeError, "#{context} versions must be a map or an array"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
private_class_method :version_entries
|
|
67
|
+
|
|
68
|
+
sig { params(value: Object, context: String).returns(T::Boolean) }
|
|
69
|
+
def self.minified?(value, context)
|
|
70
|
+
return false if value.nil?
|
|
71
|
+
return true if value == "composer/2.0"
|
|
72
|
+
|
|
73
|
+
raise TypeError, "#{context} minified must be composer/2.0 or nil"
|
|
74
|
+
end
|
|
75
|
+
private_class_method :minified?
|
|
76
|
+
|
|
77
|
+
sig { params(entries: T::Array[Object], minified: T::Boolean, context: String).returns(T::Array[Release]) }
|
|
78
|
+
def self.parse_releases(entries, minified:, context:)
|
|
79
|
+
previous = T.let(nil, T.nilable(DocumentValueParser::ObjectHash))
|
|
80
|
+
entries.each_with_index.map do |entry, index|
|
|
81
|
+
location = "#{context} releases[#{index}]"
|
|
82
|
+
fields = DocumentValueParser.object_hash(entry, location)
|
|
83
|
+
if minified
|
|
84
|
+
fields = expand_fields(previous, fields)
|
|
85
|
+
previous = fields
|
|
86
|
+
end
|
|
87
|
+
parse_release(fields, location)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
private_class_method :parse_releases
|
|
91
|
+
|
|
92
|
+
sig do
|
|
93
|
+
params(previous: T.nilable(DocumentValueParser::ObjectHash), delta: DocumentValueParser::ObjectHash)
|
|
94
|
+
.returns(DocumentValueParser::ObjectHash)
|
|
95
|
+
end
|
|
96
|
+
def self.expand_fields(previous, delta)
|
|
97
|
+
return delta if previous.nil? || previous.empty?
|
|
98
|
+
|
|
99
|
+
# composer/2.0 deltas replace top-level fields, not nested members.
|
|
100
|
+
expanded = previous.dup
|
|
101
|
+
delta.each do |key, value|
|
|
102
|
+
if value == "__unset"
|
|
103
|
+
expanded.delete(key)
|
|
104
|
+
else
|
|
105
|
+
expanded[key] = value
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
expanded
|
|
109
|
+
end
|
|
110
|
+
private_class_method :expand_fields
|
|
111
|
+
|
|
112
|
+
sig { params(fields: DocumentValueParser::ObjectHash, context: String).returns(Release) }
|
|
113
|
+
def self.parse_release(fields, context)
|
|
114
|
+
raise TypeError, "#{context}.version is required" unless fields.key?("version")
|
|
115
|
+
|
|
116
|
+
Release.new(
|
|
117
|
+
version_string: DocumentValueParser.optional_string(fields["version"], "#{context}.version"),
|
|
118
|
+
released_at: parse_time(fields["time"], "#{context}.time"),
|
|
119
|
+
url: distribution_url(fields["dist"], "#{context}.dist")
|
|
120
|
+
)
|
|
121
|
+
end
|
|
122
|
+
private_class_method :parse_release
|
|
123
|
+
|
|
124
|
+
sig { params(value: Object, context: String).returns(T.nilable(Time)) }
|
|
125
|
+
def self.parse_time(value, context)
|
|
126
|
+
string = DocumentValueParser.optional_string(value, context)
|
|
127
|
+
return if string.nil?
|
|
128
|
+
|
|
129
|
+
Time.parse(string)
|
|
130
|
+
rescue ArgumentError
|
|
131
|
+
raise TypeError.new("#{context} must be a valid timestamp"), cause: nil
|
|
132
|
+
end
|
|
133
|
+
private_class_method :parse_time
|
|
134
|
+
|
|
135
|
+
sig { params(value: Object, context: String).returns(T.nilable(String)) }
|
|
136
|
+
def self.distribution_url(value, context)
|
|
137
|
+
return if value.nil?
|
|
138
|
+
|
|
139
|
+
fields = DocumentValueParser.object_hash(value, context)
|
|
140
|
+
DocumentValueParser.optional_string(fields["url"], "#{context}.url")
|
|
141
|
+
end
|
|
142
|
+
private_class_method :distribution_url
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -519,16 +519,17 @@ module Dependabot
|
|
|
519
519
|
|
|
520
520
|
sig { returns(String) }
|
|
521
521
|
def composer_version
|
|
522
|
-
|
|
522
|
+
lockfile_document =
|
|
523
|
+
(LockfileDocument.new(data: parsed_lockfile, context: T.must(lockfile).path) if lockfile)
|
|
523
524
|
@composer_version ||= T.let(
|
|
524
|
-
Helpers.composer_version(
|
|
525
|
+
Helpers.composer_version(manifest_document, lockfile_document),
|
|
525
526
|
T.nilable(String)
|
|
526
527
|
)
|
|
527
528
|
end
|
|
528
529
|
|
|
529
530
|
sig { returns(T::Hash[String, T::Array[String]]) }
|
|
530
531
|
def initial_platform
|
|
531
|
-
platform_php = Helpers.capture_platform_php(
|
|
532
|
+
platform_php = Helpers.capture_platform_php(manifest_document)
|
|
532
533
|
|
|
533
534
|
platform = {}
|
|
534
535
|
if platform_php.is_a?(String) && requirement_valid?(platform_php)
|
|
@@ -538,7 +539,7 @@ module Dependabot
|
|
|
538
539
|
# NOTE: We *don't* include the require-dev PHP version in our initial
|
|
539
540
|
# platform. If we fail to resolve with the PHP version specified in
|
|
540
541
|
# `require` then it will be picked up in a subsequent iteration.
|
|
541
|
-
requirement_php = Helpers.php_constraint(
|
|
542
|
+
requirement_php = Helpers.php_constraint(manifest_document)
|
|
542
543
|
return platform unless requirement_php.is_a?(String)
|
|
543
544
|
return platform unless requirement_valid?(requirement_php)
|
|
544
545
|
|
|
@@ -547,6 +548,14 @@ module Dependabot
|
|
|
547
548
|
platform
|
|
548
549
|
end
|
|
549
550
|
|
|
551
|
+
sig { returns(ManifestDocument) }
|
|
552
|
+
def manifest_document
|
|
553
|
+
@manifest_document ||= T.let(
|
|
554
|
+
ManifestDocument.new(data: parsed_composer_file, context: T.must(composer_file).path),
|
|
555
|
+
T.nilable(ManifestDocument)
|
|
556
|
+
)
|
|
557
|
+
end
|
|
558
|
+
|
|
550
559
|
sig { returns(T::Hash[String, T.untyped]) }
|
|
551
560
|
def parsed_composer_file
|
|
552
561
|
@parsed_composer_file ||= T.let(
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-composer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.400.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dependabot
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 0.400.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.
|
|
25
|
+
version: 0.400.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: debug
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -254,6 +254,7 @@ files:
|
|
|
254
254
|
- helpers/v2/src/Updater.php
|
|
255
255
|
- lib/dependabot/composer.rb
|
|
256
256
|
- lib/dependabot/composer/composer_error_handler.rb
|
|
257
|
+
- lib/dependabot/composer/document_value_parser.rb
|
|
257
258
|
- lib/dependabot/composer/file_fetcher.rb
|
|
258
259
|
- lib/dependabot/composer/file_fetcher/path_dependency_builder.rb
|
|
259
260
|
- lib/dependabot/composer/file_parser.rb
|
|
@@ -262,9 +263,12 @@ files:
|
|
|
262
263
|
- lib/dependabot/composer/file_updater/manifest_updater.rb
|
|
263
264
|
- lib/dependabot/composer/helpers.rb
|
|
264
265
|
- lib/dependabot/composer/language.rb
|
|
266
|
+
- lib/dependabot/composer/lockfile_document.rb
|
|
267
|
+
- lib/dependabot/composer/manifest_document.rb
|
|
265
268
|
- lib/dependabot/composer/metadata_finder.rb
|
|
266
269
|
- lib/dependabot/composer/native_helpers.rb
|
|
267
270
|
- lib/dependabot/composer/package/package_details_fetcher.rb
|
|
271
|
+
- lib/dependabot/composer/package/registry_package.rb
|
|
268
272
|
- lib/dependabot/composer/package_manager.rb
|
|
269
273
|
- lib/dependabot/composer/requirement.rb
|
|
270
274
|
- lib/dependabot/composer/update_checker.rb
|
|
@@ -277,7 +281,7 @@ licenses:
|
|
|
277
281
|
- MIT
|
|
278
282
|
metadata:
|
|
279
283
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
280
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
284
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.400.0
|
|
281
285
|
rdoc_options: []
|
|
282
286
|
require_paths:
|
|
283
287
|
- lib
|