dependabot-hex 0.332.0 → 0.333.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/lib/dependabot/hex/file_fetcher.rb +19 -5
- data/lib/dependabot/hex/file_parser.rb +2 -0
- data/lib/dependabot/hex/file_updater/lockfile_updater.rb +43 -9
- data/lib/dependabot/hex/file_updater/mixfile_requirement_updater.rb +41 -13
- data/lib/dependabot/hex/file_updater/mixfile_sanitizer.rb +1 -0
- data/lib/dependabot/hex/file_updater/mixfile_updater.rb +20 -9
- data/lib/dependabot/hex/file_updater.rb +1 -1
- data/lib/dependabot/hex/requirement.rb +16 -5
- data/lib/dependabot/hex/update_checker/file_preparer.rb +51 -13
- data/lib/dependabot/hex/update_checker/requirements_updater.rb +50 -19
- data/lib/dependabot/hex/update_checker/version_resolver.rb +49 -10
- data/lib/dependabot/hex/update_checker.rb +15 -12
- data/lib/dependabot/hex/version.rb +11 -4
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f286072dcda605590c5ba5f897e77265f75e0fe9d8921cbe61340a4588cff115
|
4
|
+
data.tar.gz: 2a9ad6bb806461c48df4d401301752ab0a61aa0f602f7c3c4940634ccd7da268
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c16d7e0dd44dc71a9f3d2209062715588b5d238b8eb144eb63caeff4e0901448147fb423c8f6e90445af9bb6bdce5d8d8542e39ded0eaa6183513e5f7a98a4b7
|
7
|
+
data.tar.gz: 3af81cc43c90df269cd7ddb72c3e740e7e399324978abf48da0b6483bb9805b6a444f21d49a218f8e8fa9550a7b47e72a6ef7cb95eeba4bf5ee3f5516f3772d1
|
@@ -4,6 +4,7 @@
|
|
4
4
|
require "sorbet-runtime"
|
5
5
|
require "dependabot/file_fetchers"
|
6
6
|
require "dependabot/file_fetchers/base"
|
7
|
+
require "dependabot/file_filtering"
|
7
8
|
|
8
9
|
module Dependabot
|
9
10
|
module Hex
|
@@ -34,7 +35,12 @@ module Dependabot
|
|
34
35
|
fetched_files << lockfile if lockfile
|
35
36
|
fetched_files += subapp_mixfiles
|
36
37
|
fetched_files += support_files
|
37
|
-
|
38
|
+
# Apply final filtering to exclude any files that match the exclude_paths configuration
|
39
|
+
filtered_files = fetched_files.compact.reject do |file|
|
40
|
+
Dependabot::FileFiltering.should_exclude_path?(file.name, "file from final collection", @exclude_paths)
|
41
|
+
end
|
42
|
+
|
43
|
+
filtered_files
|
38
44
|
end
|
39
45
|
|
40
46
|
private
|
@@ -62,14 +68,22 @@ module Dependabot
|
|
62
68
|
&.named_captures&.fetch("path")
|
63
69
|
return [] unless apps_path
|
64
70
|
|
65
|
-
repo_contents(dir: apps_path)
|
66
|
-
|
67
|
-
|
71
|
+
directories = repo_contents(dir: apps_path)
|
72
|
+
.select { |f| f.type == "dir" }
|
73
|
+
.map { |f| File.join(apps_path, f.name) }
|
74
|
+
|
75
|
+
directories.reject do |dir|
|
76
|
+
Dependabot::FileFiltering.should_exclude_path?(dir, "umbrella app directory", @exclude_paths)
|
77
|
+
end
|
68
78
|
end
|
69
79
|
|
70
80
|
sig { returns(T::Array[String]) }
|
71
81
|
def sub_project_directories
|
72
|
-
T.must(T.must(mixfile).content).scan(PATH_DEPS_REGEX).flatten
|
82
|
+
directories = T.must(T.must(mixfile).content).scan(PATH_DEPS_REGEX).flatten
|
83
|
+
|
84
|
+
directories.reject do |dir|
|
85
|
+
Dependabot::FileFiltering.should_exclude_path?(dir, "path dependency directory", @exclude_paths)
|
86
|
+
end
|
73
87
|
end
|
74
88
|
|
75
89
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
@@ -17,8 +17,10 @@ require "dependabot/errors"
|
|
17
17
|
module Dependabot
|
18
18
|
module Hex
|
19
19
|
extend T::Sig
|
20
|
+
|
20
21
|
class FileParser < Dependabot::FileParsers::Base
|
21
22
|
extend T::Sig
|
23
|
+
|
22
24
|
require "dependabot/file_parsers/base/dependency_set"
|
23
25
|
|
24
26
|
sig { override.returns(T::Array[Dependabot::Dependency]) }
|
@@ -1,6 +1,8 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
4
6
|
require "dependabot/hex/file_updater"
|
5
7
|
require "dependabot/hex/file_updater/mixfile_updater"
|
6
8
|
require "dependabot/hex/file_updater/mixfile_sanitizer"
|
@@ -14,13 +16,24 @@ module Dependabot
|
|
14
16
|
module Hex
|
15
17
|
class FileUpdater
|
16
18
|
class LockfileUpdater
|
19
|
+
extend T::Sig
|
20
|
+
|
21
|
+
sig do
|
22
|
+
params(
|
23
|
+
dependencies: T::Array[Dependabot::Dependency],
|
24
|
+
dependency_files: T::Array[Dependabot::DependencyFile],
|
25
|
+
credentials: T::Array[Dependabot::Credential]
|
26
|
+
).void
|
27
|
+
end
|
17
28
|
def initialize(dependencies:, dependency_files:, credentials:)
|
18
|
-
@dependencies = dependencies
|
19
|
-
@dependency_files = dependency_files
|
20
|
-
@credentials = credentials
|
29
|
+
@dependencies = T.let(dependencies, T::Array[Dependabot::Dependency])
|
30
|
+
@dependency_files = T.let(dependency_files, T::Array[Dependabot::DependencyFile])
|
31
|
+
@credentials = T.let(credentials, T::Array[Dependabot::Credential])
|
21
32
|
end
|
22
33
|
|
34
|
+
sig { returns(String) }
|
23
35
|
def updated_lockfile_content
|
36
|
+
@updated_lockfile_content = T.let(@updated_lockfile_content, T.nilable(String))
|
24
37
|
@updated_lockfile_content ||=
|
25
38
|
SharedHelpers.in_a_temporary_directory do
|
26
39
|
write_temporary_dependency_files
|
@@ -41,23 +54,32 @@ module Dependabot
|
|
41
54
|
|
42
55
|
private
|
43
56
|
|
57
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
44
58
|
attr_reader :dependencies
|
59
|
+
|
60
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
45
61
|
attr_reader :dependency_files
|
62
|
+
|
63
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
46
64
|
attr_reader :credentials
|
47
65
|
|
66
|
+
sig { returns(Dependabot::Dependency) }
|
48
67
|
def dependency
|
49
68
|
# For now, we'll only ever be updating a single dep for Elixir
|
50
|
-
dependencies.first
|
69
|
+
T.must(dependencies.first)
|
51
70
|
end
|
52
71
|
|
72
|
+
sig { params(content: String).returns(String) }
|
53
73
|
def post_process_lockfile(content)
|
54
|
-
|
74
|
+
lockfile_content = T.must(lockfile.content)
|
75
|
+
return content unless lockfile_content.start_with?("%{\"")
|
55
76
|
return content if content.start_with?("%{\"")
|
56
77
|
|
57
78
|
# Substitute back old file beginning and ending
|
58
79
|
content.sub(/\A%\{\n "/, "%{\"").sub("},\n}", "}}")
|
59
80
|
end
|
60
81
|
|
82
|
+
sig { void }
|
61
83
|
def write_temporary_dependency_files
|
62
84
|
mixfiles.each do |file|
|
63
85
|
path = file.name
|
@@ -65,21 +87,23 @@ module Dependabot
|
|
65
87
|
File.write(path, mixfile_content_for_lockfile_generation(file))
|
66
88
|
end
|
67
89
|
|
68
|
-
File.write("mix.lock", lockfile.content)
|
90
|
+
File.write("mix.lock", T.must(lockfile.content))
|
69
91
|
|
70
92
|
dependency_files.select(&:support_file).each do |file|
|
71
93
|
path = file.name
|
72
94
|
FileUtils.mkdir_p(Pathname.new(path).dirname)
|
73
|
-
File.write(path, sanitize_mixfile(file.content))
|
95
|
+
File.write(path, sanitize_mixfile(T.must(file.content)))
|
74
96
|
end
|
75
97
|
end
|
76
98
|
|
99
|
+
sig { params(file: Dependabot::DependencyFile).returns(String) }
|
77
100
|
def mixfile_content_for_lockfile_generation(file)
|
78
101
|
content = updated_mixfile_content(file)
|
79
102
|
content = lock_mixfile_dependency_versions(content, file.name)
|
80
103
|
sanitize_mixfile(content)
|
81
104
|
end
|
82
105
|
|
106
|
+
sig { params(file: Dependabot::DependencyFile).returns(String) }
|
83
107
|
def updated_mixfile_content(file)
|
84
108
|
MixfileUpdater.new(
|
85
109
|
dependencies: dependencies,
|
@@ -87,6 +111,7 @@ module Dependabot
|
|
87
111
|
).updated_mixfile_content
|
88
112
|
end
|
89
113
|
|
114
|
+
sig { params(mixfile_content: String, filename: String).returns(String) }
|
90
115
|
def lock_mixfile_dependency_versions(mixfile_content, filename)
|
91
116
|
dependencies
|
92
117
|
.reduce(mixfile_content.dup) do |content, dep|
|
@@ -107,10 +132,12 @@ module Dependabot
|
|
107
132
|
end
|
108
133
|
end
|
109
134
|
|
135
|
+
sig { params(content: String).returns(String) }
|
110
136
|
def sanitize_mixfile(content)
|
111
137
|
MixfileSanitizer.new(mixfile_content: content).sanitized_content
|
112
138
|
end
|
113
139
|
|
140
|
+
sig { returns(T::Hash[String, String]) }
|
114
141
|
def mix_env
|
115
142
|
{
|
116
143
|
"MIX_EXS" => File.join(NativeHelpers.hex_helpers_dir, "mix.exs"),
|
@@ -118,20 +145,27 @@ module Dependabot
|
|
118
145
|
}
|
119
146
|
end
|
120
147
|
|
148
|
+
sig { returns(String) }
|
121
149
|
def elixir_helper_path
|
122
150
|
File.join(NativeHelpers.hex_helpers_dir, "lib/run.exs")
|
123
151
|
end
|
124
152
|
|
153
|
+
sig { returns(String) }
|
125
154
|
def elixir_helper_do_update_path
|
126
155
|
File.join(NativeHelpers.hex_helpers_dir, "lib/do_update.exs")
|
127
156
|
end
|
128
157
|
|
158
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
129
159
|
def mixfiles
|
130
160
|
dependency_files.select { |f| f.name.end_with?("mix.exs") }
|
131
161
|
end
|
132
162
|
|
163
|
+
sig { returns(Dependabot::DependencyFile) }
|
133
164
|
def lockfile
|
134
|
-
@lockfile ||=
|
165
|
+
@lockfile ||= T.let(
|
166
|
+
T.must(dependency_files.find { |f| f.name == "mix.lock" }),
|
167
|
+
T.nilable(Dependabot::DependencyFile)
|
168
|
+
)
|
135
169
|
end
|
136
170
|
end
|
137
171
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
4
6
|
require "dependabot/hex/file_updater"
|
5
7
|
require "dependabot/shared_helpers"
|
6
8
|
|
@@ -8,16 +10,28 @@ module Dependabot
|
|
8
10
|
module Hex
|
9
11
|
class FileUpdater
|
10
12
|
class MixfileRequirementUpdater
|
13
|
+
extend T::Sig
|
14
|
+
|
15
|
+
sig do
|
16
|
+
params(
|
17
|
+
dependency_name: String,
|
18
|
+
mixfile_content: String,
|
19
|
+
previous_requirement: T.nilable(String),
|
20
|
+
updated_requirement: T.nilable(String),
|
21
|
+
insert_if_bare: T::Boolean
|
22
|
+
).void
|
23
|
+
end
|
11
24
|
def initialize(dependency_name:, mixfile_content:,
|
12
25
|
previous_requirement:, updated_requirement:,
|
13
26
|
insert_if_bare: false)
|
14
|
-
@dependency_name = dependency_name
|
15
|
-
@mixfile_content = mixfile_content
|
16
|
-
@previous_requirement = previous_requirement
|
17
|
-
@updated_requirement = updated_requirement
|
18
|
-
@insert_if_bare = insert_if_bare
|
27
|
+
@dependency_name = T.let(dependency_name, String)
|
28
|
+
@mixfile_content = T.let(mixfile_content, String)
|
29
|
+
@previous_requirement = T.let(previous_requirement, T.nilable(String))
|
30
|
+
@updated_requirement = T.let(updated_requirement, T.nilable(String))
|
31
|
+
@insert_if_bare = T.let(insert_if_bare, T::Boolean)
|
19
32
|
end
|
20
33
|
|
34
|
+
sig { returns(String) }
|
21
35
|
def updated_content
|
22
36
|
updated_content = update_requirement(mixfile_content)
|
23
37
|
|
@@ -28,15 +42,24 @@ module Dependabot
|
|
28
42
|
|
29
43
|
private
|
30
44
|
|
45
|
+
sig { returns(String) }
|
31
46
|
attr_reader :dependency_name
|
47
|
+
|
48
|
+
sig { returns(String) }
|
32
49
|
attr_reader :mixfile_content
|
50
|
+
|
51
|
+
sig { returns(T.nilable(String)) }
|
33
52
|
attr_reader :previous_requirement
|
53
|
+
|
54
|
+
sig { returns(T.nilable(String)) }
|
34
55
|
attr_reader :updated_requirement
|
35
56
|
|
57
|
+
sig { returns(T::Boolean) }
|
36
58
|
def insert_if_bare?
|
37
|
-
|
59
|
+
@insert_if_bare
|
38
60
|
end
|
39
61
|
|
62
|
+
sig { params(content: String).returns(String) }
|
40
63
|
def update_requirement(content)
|
41
64
|
return content if previous_requirement.nil? && !insert_if_bare?
|
42
65
|
|
@@ -44,28 +67,33 @@ module Dependabot
|
|
44
67
|
if previous_requirement
|
45
68
|
/
|
46
69
|
:#{Regexp.escape(dependency_name)}\s*,.*
|
47
|
-
#{Regexp.escape(previous_requirement)}
|
70
|
+
#{Regexp.escape(T.must(previous_requirement))}
|
48
71
|
/x
|
49
72
|
else
|
50
73
|
/:#{Regexp.escape(dependency_name)}(,|\s|\})/
|
51
74
|
end
|
52
75
|
|
53
76
|
content.gsub(requirement_line_regex) do |requirement_line|
|
54
|
-
if previous_requirement
|
55
|
-
requirement_line.gsub(previous_requirement, updated_requirement)
|
56
|
-
|
77
|
+
if previous_requirement && updated_requirement
|
78
|
+
requirement_line.gsub(T.must(previous_requirement), T.must(updated_requirement))
|
79
|
+
elsif updated_requirement
|
57
80
|
requirement_line.gsub(
|
58
81
|
":#{dependency_name}",
|
59
|
-
":#{dependency_name}, \"#{updated_requirement}\""
|
82
|
+
":#{dependency_name}, \"#{T.must(updated_requirement)}\""
|
60
83
|
)
|
84
|
+
else
|
85
|
+
# If we don't have an updated requirement, return the line unchanged
|
86
|
+
requirement_line
|
61
87
|
end
|
62
88
|
end
|
63
89
|
end
|
64
90
|
|
91
|
+
sig { returns(T::Boolean) }
|
65
92
|
def content_should_change?
|
66
93
|
return false if previous_requirement == updated_requirement
|
94
|
+
return false if updated_requirement.nil? && !insert_if_bare?
|
67
95
|
|
68
|
-
previous_requirement || insert_if_bare?
|
96
|
+
!previous_requirement.nil? || insert_if_bare?
|
69
97
|
end
|
70
98
|
end
|
71
99
|
end
|
@@ -1,6 +1,7 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "sorbet-runtime"
|
4
5
|
require "dependabot/hex/file_updater"
|
5
6
|
require "dependabot/hex/file_updater/mixfile_requirement_updater"
|
6
7
|
require "dependabot/hex/file_updater/mixfile_git_pin_updater"
|
@@ -9,15 +10,19 @@ module Dependabot
|
|
9
10
|
module Hex
|
10
11
|
class FileUpdater
|
11
12
|
class MixfileUpdater
|
13
|
+
extend T::Sig
|
14
|
+
|
15
|
+
sig { params(mixfile: Dependabot::DependencyFile, dependencies: T::Array[Dependabot::Dependency]).void }
|
12
16
|
def initialize(mixfile:, dependencies:)
|
13
|
-
@mixfile = mixfile
|
14
|
-
@dependencies = dependencies
|
17
|
+
@mixfile = T.let(mixfile, Dependabot::DependencyFile)
|
18
|
+
@dependencies = T.let(dependencies, T::Array[Dependabot::Dependency])
|
15
19
|
end
|
16
20
|
|
21
|
+
sig { returns(String) }
|
17
22
|
def updated_mixfile_content
|
18
23
|
dependencies
|
19
24
|
.select { |dep| requirement_changed?(mixfile, dep) }
|
20
|
-
.reduce(mixfile.content.dup) do |content, dep|
|
25
|
+
.reduce(T.must(mixfile.content).dup) do |content, dep|
|
21
26
|
updated_content = content
|
22
27
|
|
23
28
|
updated_content = update_requirement(
|
@@ -40,25 +45,30 @@ module Dependabot
|
|
40
45
|
|
41
46
|
private
|
42
47
|
|
48
|
+
sig { returns(Dependabot::DependencyFile) }
|
43
49
|
attr_reader :mixfile
|
50
|
+
|
51
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
44
52
|
attr_reader :dependencies
|
45
53
|
|
54
|
+
sig { params(file: Dependabot::DependencyFile, dependency: Dependabot::Dependency).returns(T::Boolean) }
|
46
55
|
def requirement_changed?(file, dependency)
|
47
56
|
changed_requirements =
|
48
|
-
dependency.requirements - dependency.previous_requirements
|
57
|
+
dependency.requirements - (dependency.previous_requirements || [])
|
49
58
|
|
50
59
|
changed_requirements.any? { |f| f[:file] == file.name }
|
51
60
|
end
|
52
61
|
|
62
|
+
sig { params(content: String, filename: String, dependency: Dependabot::Dependency).returns(String) }
|
53
63
|
def update_requirement(content:, filename:, dependency:)
|
54
64
|
updated_req =
|
55
65
|
dependency.requirements.find { |r| r[:file] == filename }
|
56
|
-
|
66
|
+
&.fetch(:requirement)
|
57
67
|
|
58
68
|
old_req =
|
59
69
|
dependency.previous_requirements
|
60
|
-
|
61
|
-
|
70
|
+
&.find { |r| r[:file] == filename }
|
71
|
+
&.fetch(:requirement)
|
62
72
|
|
63
73
|
return content unless old_req
|
64
74
|
|
@@ -70,6 +80,7 @@ module Dependabot
|
|
70
80
|
).updated_content
|
71
81
|
end
|
72
82
|
|
83
|
+
sig { params(content: String, filename: String, dependency: Dependabot::Dependency).returns(String) }
|
73
84
|
def update_git_pin(content:, filename:, dependency:)
|
74
85
|
updated_pin =
|
75
86
|
dependency.requirements.find { |r| r[:file] == filename }
|
@@ -77,7 +88,7 @@ module Dependabot
|
|
77
88
|
|
78
89
|
old_pin =
|
79
90
|
dependency.previous_requirements
|
80
|
-
|
91
|
+
&.find { |r| r[:file] == filename }
|
81
92
|
&.dig(:source, :ref)
|
82
93
|
|
83
94
|
return content unless old_pin
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "sorbet-runtime"
|
@@ -16,11 +16,16 @@ module Dependabot
|
|
16
16
|
OR_SEPARATOR = /\s+or\s+/
|
17
17
|
|
18
18
|
# Add the double-equality matcher to the list of allowed operations
|
19
|
-
OPS =
|
19
|
+
OPS = T.let(
|
20
|
+
OPS.merge("==" => lambda { |v, r|
|
21
|
+
v == r
|
22
|
+
}),
|
23
|
+
T::Hash[String, T.proc.params(arg0: Gem::Version, arg1: Gem::Version).returns(T::Boolean)]
|
24
|
+
)
|
20
25
|
|
21
26
|
# Override the version pattern to allow local versions
|
22
|
-
quoted = OPS.keys.map { |k| Regexp.quote k }.join
|
23
|
-
PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Hex::Version::VERSION_PATTERN})\\s*".freeze
|
27
|
+
quoted = OPS.keys.map { |k| Regexp.quote k }.join("|")
|
28
|
+
PATTERN_RAW = T.let("\\s*(#{quoted})?\\s*(#{Hex::Version::VERSION_PATTERN})\\s*".freeze, String)
|
24
29
|
PATTERN = /\A#{PATTERN_RAW}\z/
|
25
30
|
|
26
31
|
# Returns an array of requirements. At least one requirement from the
|
@@ -35,6 +40,7 @@ module Dependabot
|
|
35
40
|
|
36
41
|
# Patches Gem::Requirement to make it accept requirement strings like
|
37
42
|
# "~> 4.2.5, >= 4.2.5.1" without first needing to split them.
|
43
|
+
sig { params(requirements: T.any(String, T::Array[String])).void }
|
38
44
|
def initialize(*requirements)
|
39
45
|
requirements = requirements.flatten.flat_map do |req_string|
|
40
46
|
req_string.split(",").map(&:strip)
|
@@ -44,6 +50,10 @@ module Dependabot
|
|
44
50
|
end
|
45
51
|
|
46
52
|
# Override the parser to create Hex::Versions
|
53
|
+
sig do
|
54
|
+
params(obj: T.any(String, Gem::Version))
|
55
|
+
.returns(T::Array[T.any(String, Gem::Version)])
|
56
|
+
end
|
47
57
|
def self.parse(obj)
|
48
58
|
return ["=", Hex::Version.new(obj.to_s)] if obj.is_a?(Gem::Version)
|
49
59
|
|
@@ -57,10 +67,11 @@ module Dependabot
|
|
57
67
|
[matches[1] || "=", Hex::Version.new(T.must(matches[2]))]
|
58
68
|
end
|
59
69
|
|
70
|
+
sig { params(version: T.any(String, Gem::Version, Dependabot::Version)).returns(T::Boolean) }
|
60
71
|
def satisfied_by?(version)
|
61
72
|
version = Hex::Version.new(version.to_s)
|
62
73
|
|
63
|
-
requirements.all? { |op, rv| (OPS[op] || OPS["="]).call(version, rv) }
|
74
|
+
requirements.all? { |op, rv| T.must(OPS[op] || OPS["="]).call(version, rv) }
|
64
75
|
end
|
65
76
|
end
|
66
77
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "sorbet-runtime"
|
@@ -18,17 +18,27 @@ module Dependabot
|
|
18
18
|
class FilePreparer
|
19
19
|
extend T::Sig
|
20
20
|
|
21
|
+
sig do
|
22
|
+
params(
|
23
|
+
dependency_files: T::Array[Dependabot::DependencyFile],
|
24
|
+
dependency: Dependabot::Dependency,
|
25
|
+
unlock_requirement: T.any(T.nilable(Symbol), T::Boolean),
|
26
|
+
replacement_git_pin: T.nilable(String),
|
27
|
+
latest_allowable_version: T.nilable(Gem::Version)
|
28
|
+
).void
|
29
|
+
end
|
21
30
|
def initialize(dependency_files:, dependency:,
|
22
31
|
unlock_requirement: true,
|
23
32
|
replacement_git_pin: nil,
|
24
33
|
latest_allowable_version: nil)
|
25
|
-
@dependency_files = dependency_files
|
26
|
-
@dependency = dependency
|
27
|
-
@unlock_requirement = unlock_requirement
|
28
|
-
@replacement_git_pin = replacement_git_pin
|
29
|
-
@latest_allowable_version = latest_allowable_version
|
34
|
+
@dependency_files = T.let(dependency_files, T::Array[Dependabot::DependencyFile])
|
35
|
+
@dependency = T.let(dependency, Dependabot::Dependency)
|
36
|
+
@unlock_requirement = T.let(unlock_requirement ? true : false, T::Boolean)
|
37
|
+
@replacement_git_pin = T.let(replacement_git_pin, T.nilable(String))
|
38
|
+
@latest_allowable_version = T.let(latest_allowable_version, T.nilable(Gem::Version))
|
30
39
|
end
|
31
40
|
|
41
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
32
42
|
def prepared_dependency_files
|
33
43
|
files = []
|
34
44
|
files += mixfiles.map do |file|
|
@@ -45,21 +55,31 @@ module Dependabot
|
|
45
55
|
|
46
56
|
private
|
47
57
|
|
58
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
48
59
|
attr_reader :dependency_files
|
60
|
+
|
61
|
+
sig { returns(Dependabot::Dependency) }
|
49
62
|
attr_reader :dependency
|
63
|
+
|
64
|
+
sig { returns(T.nilable(String)) }
|
50
65
|
attr_reader :replacement_git_pin
|
66
|
+
|
67
|
+
sig { returns(T.nilable(Gem::Version)) }
|
51
68
|
attr_reader :latest_allowable_version
|
52
69
|
|
70
|
+
sig { returns(T::Boolean) }
|
53
71
|
def unlock_requirement?
|
54
72
|
@unlock_requirement
|
55
73
|
end
|
56
74
|
|
75
|
+
sig { returns(T::Boolean) }
|
57
76
|
def replace_git_pin?
|
58
77
|
!replacement_git_pin.nil?
|
59
78
|
end
|
60
79
|
|
80
|
+
sig { params(file: Dependabot::DependencyFile).returns(String) }
|
61
81
|
def mixfile_content_for_update_check(file)
|
62
|
-
content = file.content
|
82
|
+
content = T.must(file.content)
|
63
83
|
|
64
84
|
return sanitize_mixfile(content) unless dependency_appears_in_file?(file.name)
|
65
85
|
|
@@ -69,10 +89,11 @@ module Dependabot
|
|
69
89
|
sanitize_mixfile(content)
|
70
90
|
end
|
71
91
|
|
92
|
+
sig { params(content: String, filename: String).returns(String) }
|
72
93
|
def relax_version(content, filename:)
|
73
94
|
old_requirement =
|
74
95
|
dependency.requirements.find { |r| r.fetch(:file) == filename }
|
75
|
-
|
96
|
+
&.fetch(:requirement)
|
76
97
|
updated_requirement = updated_version_requirement_string(filename)
|
77
98
|
|
78
99
|
Hex::FileUpdater::MixfileRequirementUpdater.new(
|
@@ -80,10 +101,11 @@ module Dependabot
|
|
80
101
|
mixfile_content: content,
|
81
102
|
previous_requirement: old_requirement,
|
82
103
|
updated_requirement: updated_requirement,
|
83
|
-
insert_if_bare: updated_requirement
|
104
|
+
insert_if_bare: !updated_requirement.nil?
|
84
105
|
).updated_content
|
85
106
|
end
|
86
107
|
|
108
|
+
sig { params(filename: String).returns(T.nilable(String)) }
|
87
109
|
def updated_version_requirement_string(filename)
|
88
110
|
lower_bound_req = updated_version_req_lower_bound(filename)
|
89
111
|
|
@@ -96,6 +118,7 @@ module Dependabot
|
|
96
118
|
# rubocop:disable Metrics/AbcSize
|
97
119
|
# rubocop:disable Metrics/PerceivedComplexity
|
98
120
|
# rubocop:disable Metrics/CyclomaticComplexity
|
121
|
+
sig { params(filename: String).returns(String) }
|
99
122
|
def updated_version_req_lower_bound(filename)
|
100
123
|
original_req = dependency.requirements
|
101
124
|
.find { |r| r.fetch(:file) == filename }
|
@@ -126,6 +149,7 @@ module Dependabot
|
|
126
149
|
# rubocop:enable Metrics/CyclomaticComplexity
|
127
150
|
# rubocop:enable Metrics/AbcSize
|
128
151
|
|
152
|
+
sig { params(content: String, filename: String).returns(String) }
|
129
153
|
def replace_git_pin(content, filename:)
|
130
154
|
old_pin =
|
131
155
|
dependency.requirements.find { |r| r.fetch(:file) == filename }
|
@@ -138,16 +162,18 @@ module Dependabot
|
|
138
162
|
dependency_name: dependency.name,
|
139
163
|
mixfile_content: content,
|
140
164
|
previous_pin: old_pin,
|
141
|
-
updated_pin: replacement_git_pin
|
165
|
+
updated_pin: T.must(replacement_git_pin)
|
142
166
|
).updated_content
|
143
167
|
end
|
144
168
|
|
169
|
+
sig { params(content: String).returns(String) }
|
145
170
|
def sanitize_mixfile(content)
|
146
171
|
Hex::FileUpdater::MixfileSanitizer.new(
|
147
172
|
mixfile_content: content
|
148
173
|
).sanitized_content
|
149
174
|
end
|
150
175
|
|
176
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
151
177
|
def mixfiles
|
152
178
|
mixfiles =
|
153
179
|
dependency_files
|
@@ -157,14 +183,23 @@ module Dependabot
|
|
157
183
|
mixfiles
|
158
184
|
end
|
159
185
|
|
186
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
160
187
|
def lockfile
|
161
|
-
@lockfile ||=
|
188
|
+
@lockfile ||= T.let(
|
189
|
+
dependency_files.find { |f| f.name == "mix.lock" },
|
190
|
+
T.nilable(Dependabot::DependencyFile)
|
191
|
+
)
|
162
192
|
end
|
163
193
|
|
194
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
164
195
|
def support_files
|
165
|
-
@support_files ||=
|
196
|
+
@support_files ||= T.let(
|
197
|
+
dependency_files.select(&:support_file),
|
198
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
199
|
+
)
|
166
200
|
end
|
167
201
|
|
202
|
+
sig { returns(T::Boolean) }
|
168
203
|
def wants_prerelease?
|
169
204
|
current_version = dependency.version
|
170
205
|
if current_version &&
|
@@ -178,14 +213,17 @@ module Dependabot
|
|
178
213
|
end
|
179
214
|
end
|
180
215
|
|
216
|
+
sig { returns(T.class_of(Dependabot::Version)) }
|
181
217
|
def version_class
|
182
218
|
dependency.version_class
|
183
219
|
end
|
184
220
|
|
221
|
+
sig { returns(Regexp) }
|
185
222
|
def version_regex
|
186
|
-
Dependabot::Hex::Version::VERSION_PATTERN
|
223
|
+
Regexp.new(Dependabot::Hex::Version::VERSION_PATTERN)
|
187
224
|
end
|
188
225
|
|
226
|
+
sig { params(file_name: String).returns(T::Boolean) }
|
189
227
|
def dependency_appears_in_file?(file_name)
|
190
228
|
dependency.requirements.any? { |r| r[:file] == file_name }
|
191
229
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
4
6
|
require "dependabot/hex/version"
|
5
7
|
require "dependabot/hex/requirement"
|
6
8
|
require "dependabot/hex/update_checker"
|
@@ -9,34 +11,50 @@ module Dependabot
|
|
9
11
|
module Hex
|
10
12
|
class UpdateChecker
|
11
13
|
class RequirementsUpdater
|
14
|
+
extend T::Sig
|
15
|
+
|
12
16
|
OPERATORS = />=|<=|>|<|==|~>/
|
13
17
|
AND_SEPARATOR = /\s+and\s+/
|
14
18
|
OR_SEPARATOR = /\s+or\s+/
|
15
19
|
SEPARATOR = /#{AND_SEPARATOR}|#{OR_SEPARATOR}/
|
16
20
|
|
21
|
+
sig do
|
22
|
+
params(
|
23
|
+
requirements: T::Array[T::Hash[Symbol, T.untyped]],
|
24
|
+
latest_resolvable_version: T.nilable(String),
|
25
|
+
updated_source: T.nilable(T::Hash[Symbol, T.nilable(String)])
|
26
|
+
).void
|
27
|
+
end
|
17
28
|
def initialize(requirements:, latest_resolvable_version:,
|
18
29
|
updated_source:)
|
19
|
-
@requirements = requirements
|
20
|
-
@updated_source = updated_source
|
30
|
+
@requirements = T.let(requirements, T::Array[T::Hash[Symbol, T.untyped]])
|
31
|
+
@updated_source = T.let(updated_source, T.nilable(T::Hash[Symbol, T.nilable(String)]))
|
32
|
+
@latest_resolvable_version = T.let(nil, T.nilable(Dependabot::Version))
|
21
33
|
|
22
34
|
return unless latest_resolvable_version
|
23
35
|
return unless Hex::Version.correct?(latest_resolvable_version)
|
24
36
|
|
25
|
-
@latest_resolvable_version =
|
26
|
-
Hex::Version.new(latest_resolvable_version)
|
37
|
+
@latest_resolvable_version = Hex::Version.new(latest_resolvable_version)
|
27
38
|
end
|
28
39
|
|
40
|
+
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
29
41
|
def updated_requirements
|
30
42
|
requirements.map { |req| updated_mixfile_requirement(req) }
|
31
43
|
end
|
32
44
|
|
33
45
|
private
|
34
46
|
|
47
|
+
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
35
48
|
attr_reader :requirements
|
49
|
+
|
50
|
+
sig { returns(T.nilable(Dependabot::Version)) }
|
36
51
|
attr_reader :latest_resolvable_version
|
52
|
+
|
53
|
+
sig { returns(T.nilable(T::Hash[Symbol, T.nilable(String)])) }
|
37
54
|
attr_reader :updated_source
|
38
55
|
# rubocop:disable Metrics/PerceivedComplexity
|
39
56
|
# rubocop:disable Metrics/AbcSize
|
57
|
+
sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
|
40
58
|
def updated_mixfile_requirement(req)
|
41
59
|
req = update_source(req)
|
42
60
|
return req unless latest_resolvable_version && req[:requirement]
|
@@ -49,10 +67,10 @@ module Dependabot
|
|
49
67
|
new_requirement =
|
50
68
|
if last_string_reqs.any? { |r| r.match(/^(?:\d|=)/) }
|
51
69
|
exact_req = last_string_reqs.find { |r| r.match(/^(?:\d|=)/) }
|
52
|
-
update_exact_version(exact_req, latest_resolvable_version).to_s
|
70
|
+
update_exact_version(exact_req, T.must(latest_resolvable_version)).to_s
|
53
71
|
elsif last_string_reqs.any? { |r| r.start_with?("~>") }
|
54
72
|
tw_req = last_string_reqs.find { |r| r.start_with?("~>") }
|
55
|
-
update_twiddle_version(tw_req, latest_resolvable_version).to_s
|
73
|
+
update_twiddle_version(tw_req, T.must(latest_resolvable_version)).to_s
|
56
74
|
else
|
57
75
|
update_mixfile_range(last_string_reqs).map(&:to_s).join(" and ")
|
58
76
|
end
|
@@ -64,6 +82,7 @@ module Dependabot
|
|
64
82
|
# rubocop:enable Metrics/AbcSize
|
65
83
|
# rubocop:enable Metrics/PerceivedComplexity
|
66
84
|
|
85
|
+
sig { params(requirement_hash: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
|
67
86
|
def update_source(requirement_hash)
|
68
87
|
# Only git sources ever need to be updated. Anything else should be
|
69
88
|
# left alone.
|
@@ -72,15 +91,18 @@ module Dependabot
|
|
72
91
|
requirement_hash.merge(source: updated_source)
|
73
92
|
end
|
74
93
|
|
94
|
+
sig { params(requirement_string: String).returns(T::Boolean) }
|
75
95
|
def req_satisfied_by_latest_resolvable?(requirement_string)
|
76
96
|
ruby_requirements(requirement_string)
|
77
|
-
.any? { |r| r.satisfied_by?(latest_resolvable_version) }
|
97
|
+
.any? { |r| r.satisfied_by?(T.must(latest_resolvable_version)) }
|
78
98
|
end
|
79
99
|
|
100
|
+
sig { params(requirement_string: String).returns(T::Array[Hex::Requirement]) }
|
80
101
|
def ruby_requirements(requirement_string)
|
81
102
|
requirement_class.requirements_array(requirement_string)
|
82
103
|
end
|
83
104
|
|
105
|
+
sig { params(previous_req: String, new_version: Dependabot::Version).returns(String) }
|
84
106
|
def update_exact_version(previous_req, new_version)
|
85
107
|
op = previous_req.match(OPERATORS).to_s
|
86
108
|
old_version =
|
@@ -89,6 +111,7 @@ module Dependabot
|
|
89
111
|
"#{op} #{updated_version}".strip
|
90
112
|
end
|
91
113
|
|
114
|
+
sig { params(previous_req: String, new_version: Dependabot::Version).returns(Hex::Requirement) }
|
92
115
|
def update_twiddle_version(previous_req, new_version)
|
93
116
|
previous_req = requirement_class.new(previous_req)
|
94
117
|
old_version = previous_req.requirements.first.last
|
@@ -96,15 +119,16 @@ module Dependabot
|
|
96
119
|
requirement_class.new("~> #{updated_version}")
|
97
120
|
end
|
98
121
|
|
122
|
+
sig { params(requirements: T::Array[String]).returns(T::Array[Hex::Requirement]) }
|
99
123
|
def update_mixfile_range(requirements)
|
100
124
|
requirements = requirements.map { |r| requirement_class.new(r) }
|
101
125
|
updated_requirements =
|
102
126
|
requirements.flat_map do |r|
|
103
|
-
next r if r.satisfied_by?(latest_resolvable_version)
|
127
|
+
next r if r.satisfied_by?(T.must(latest_resolvable_version))
|
104
128
|
|
105
129
|
case op = r.requirements.first.first
|
106
130
|
when "<", "<="
|
107
|
-
[update_greatest_version(r, latest_resolvable_version)]
|
131
|
+
[update_greatest_version(r, T.must(latest_resolvable_version))]
|
108
132
|
when "!="
|
109
133
|
[]
|
110
134
|
else
|
@@ -116,6 +140,7 @@ module Dependabot
|
|
116
140
|
binding_requirements(updated_requirements)
|
117
141
|
end
|
118
142
|
|
143
|
+
sig { params(new_version: Dependabot::Version, old_version: Dependabot::Version).returns(String) }
|
119
144
|
def at_same_precision(new_version, old_version)
|
120
145
|
precision = old_version.to_s.split(".").count
|
121
146
|
new_version.to_s.split(".").first(precision).join(".")
|
@@ -123,11 +148,10 @@ module Dependabot
|
|
123
148
|
|
124
149
|
# Updates the version in a "<" or "<=" constraint to allow the given
|
125
150
|
# version
|
151
|
+
sig do
|
152
|
+
params(requirement: Hex::Requirement, version_to_be_permitted: Dependabot::Version).returns(Hex::Requirement)
|
153
|
+
end
|
126
154
|
def update_greatest_version(requirement, version_to_be_permitted)
|
127
|
-
if version_to_be_permitted.is_a?(String)
|
128
|
-
version_to_be_permitted =
|
129
|
-
Hex::Version.new(version_to_be_permitted)
|
130
|
-
end
|
131
155
|
op, version = requirement.requirements.first
|
132
156
|
version = version.release if version.prerelease?
|
133
157
|
|
@@ -138,7 +162,7 @@ module Dependabot
|
|
138
162
|
if index < index_to_update
|
139
163
|
version_to_be_permitted.segments[index]
|
140
164
|
elsif index == index_to_update
|
141
|
-
version_to_be_permitted.segments[index] + 1
|
165
|
+
version_to_be_permitted.segments[index].to_i + 1
|
142
166
|
else
|
143
167
|
0
|
144
168
|
end
|
@@ -147,22 +171,29 @@ module Dependabot
|
|
147
171
|
requirement_class.new("#{op} #{new_segments.join('.')}")
|
148
172
|
end
|
149
173
|
|
174
|
+
sig { params(requirements: T::Array[Hex::Requirement]).returns(T::Array[Hex::Requirement]) }
|
150
175
|
def binding_requirements(requirements)
|
151
176
|
grouped_by_operator =
|
152
177
|
requirements.group_by { |r| r.requirements.first.first }
|
153
178
|
|
154
179
|
binding_reqs = grouped_by_operator.flat_map do |operator, reqs|
|
155
180
|
case operator
|
156
|
-
when "<", "<="
|
157
|
-
|
158
|
-
|
181
|
+
when "<", "<="
|
182
|
+
min_req = reqs.min_by { |r| r.requirements.first.last }
|
183
|
+
min_req ? [min_req] : []
|
184
|
+
when ">", ">="
|
185
|
+
max_req = reqs.max_by { |r| r.requirements.first.last }
|
186
|
+
max_req ? [max_req] : []
|
187
|
+
else
|
188
|
+
requirements
|
159
189
|
end
|
160
|
-
end.uniq
|
190
|
+
end.uniq.compact
|
161
191
|
|
162
192
|
binding_reqs << requirement_class.new if binding_reqs.empty?
|
163
193
|
binding_reqs.sort_by { |r| r.requirements.first.last }
|
164
194
|
end
|
165
195
|
|
196
|
+
sig { returns(T.class_of(Hex::Requirement)) }
|
166
197
|
def requirement_class
|
167
198
|
Hex::Requirement
|
168
199
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
4
6
|
require "dependabot/hex/version"
|
5
7
|
require "dependabot/hex/update_checker"
|
6
8
|
require "dependabot/hex/credential_helpers"
|
@@ -13,25 +15,45 @@ module Dependabot
|
|
13
15
|
module Hex
|
14
16
|
class UpdateChecker
|
15
17
|
class VersionResolver
|
18
|
+
extend T::Sig
|
19
|
+
|
20
|
+
sig do
|
21
|
+
params(
|
22
|
+
dependency: Dependabot::Dependency,
|
23
|
+
credentials: T::Array[Dependabot::Credential],
|
24
|
+
original_dependency_files: T::Array[Dependabot::DependencyFile],
|
25
|
+
prepared_dependency_files: T::Array[Dependabot::DependencyFile]
|
26
|
+
).void
|
27
|
+
end
|
16
28
|
def initialize(dependency:, credentials:,
|
17
29
|
original_dependency_files:, prepared_dependency_files:)
|
18
|
-
@dependency = dependency
|
19
|
-
@original_dependency_files = original_dependency_files
|
20
|
-
@prepared_dependency_files = prepared_dependency_files
|
21
|
-
@credentials = credentials
|
30
|
+
@dependency = T.let(dependency, Dependabot::Dependency)
|
31
|
+
@original_dependency_files = T.let(original_dependency_files, T::Array[Dependabot::DependencyFile])
|
32
|
+
@prepared_dependency_files = T.let(prepared_dependency_files, T::Array[Dependabot::DependencyFile])
|
33
|
+
@credentials = T.let(credentials, T::Array[Dependabot::Credential])
|
34
|
+
@latest_resolvable_version = T.let(nil, T.nilable(T.any(Dependabot::Version, String, T::Boolean)))
|
22
35
|
end
|
23
36
|
|
37
|
+
sig { returns(T.nilable(T.any(Dependabot::Version, String, T::Boolean))) }
|
24
38
|
def latest_resolvable_version
|
25
39
|
@latest_resolvable_version ||= fetch_latest_resolvable_version
|
26
40
|
end
|
27
41
|
|
28
42
|
private
|
29
43
|
|
44
|
+
sig { returns(Dependabot::Dependency) }
|
30
45
|
attr_reader :dependency
|
46
|
+
|
47
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
31
48
|
attr_reader :credentials
|
49
|
+
|
50
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
32
51
|
attr_reader :original_dependency_files
|
52
|
+
|
53
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
33
54
|
attr_reader :prepared_dependency_files
|
34
55
|
|
56
|
+
sig { returns(T.nilable(T.any(Dependabot::Version, String, T::Boolean))) }
|
35
57
|
def fetch_latest_resolvable_version
|
36
58
|
latest_resolvable_version =
|
37
59
|
SharedHelpers.in_a_temporary_directory do
|
@@ -51,6 +73,7 @@ module Dependabot
|
|
51
73
|
handle_hex_errors(e)
|
52
74
|
end
|
53
75
|
|
76
|
+
sig { returns(String) }
|
54
77
|
def run_elixir_update_checker
|
55
78
|
SharedHelpers.run_helper_subprocess(
|
56
79
|
env: mix_env,
|
@@ -61,6 +84,10 @@ module Dependabot
|
|
61
84
|
)
|
62
85
|
end
|
63
86
|
|
87
|
+
sig do
|
88
|
+
params(error: Dependabot::SharedHelpers::HelperSubprocessFailed)
|
89
|
+
.returns(T.nilable(T.any(Dependabot::Version, String, T::Boolean)))
|
90
|
+
end
|
64
91
|
def handle_hex_errors(error)
|
65
92
|
if (match = error.message.match(/No authenticated organization found for (?<repo>[a-z_]+)\./))
|
66
93
|
raise Dependabot::PrivateSourceAuthenticationFailure, match[:repo]
|
@@ -98,25 +125,31 @@ module Dependabot
|
|
98
125
|
raise error
|
99
126
|
end
|
100
127
|
|
128
|
+
sig do
|
129
|
+
params(error: Dependabot::SharedHelpers::HelperSubprocessFailed).returns(T.any(Dependabot::Version, String,
|
130
|
+
T::Boolean))
|
131
|
+
end
|
101
132
|
def error_result(error)
|
102
133
|
return false unless includes_result?(error)
|
103
134
|
|
104
|
-
result_json = error.message
|
105
|
-
result = JSON.parse(result_json)["result"]
|
135
|
+
result_json = error.message.split("\n").last
|
136
|
+
result = JSON.parse(T.must(result_json))["result"]
|
106
137
|
return version_class.new(result) if version_class.correct?(result)
|
107
138
|
|
108
139
|
result
|
109
140
|
end
|
110
141
|
|
142
|
+
sig { params(error: Dependabot::SharedHelpers::HelperSubprocessFailed).returns(T::Boolean) }
|
111
143
|
def includes_result?(error)
|
112
|
-
result = error.message
|
144
|
+
result = error.message.split("\n").last
|
113
145
|
return false unless result
|
114
146
|
|
115
|
-
JSON.parse(
|
147
|
+
JSON.parse(result).key?("result")
|
116
148
|
rescue JSON::ParserError
|
117
149
|
false
|
118
150
|
end
|
119
151
|
|
152
|
+
sig { returns(T.any(T::Boolean, Dependabot::Version, String)) }
|
120
153
|
def check_original_requirements_resolvable
|
121
154
|
SharedHelpers.in_a_temporary_directory do
|
122
155
|
write_temporary_sanitized_dependency_files(prepared: false)
|
@@ -141,6 +174,7 @@ module Dependabot
|
|
141
174
|
raise Dependabot::DependencyFileNotResolvable, e.message
|
142
175
|
end
|
143
176
|
|
177
|
+
sig { params(prepared: T::Boolean).void }
|
144
178
|
def write_temporary_sanitized_dependency_files(prepared: true)
|
145
179
|
files = if prepared then prepared_dependency_files
|
146
180
|
else
|
@@ -150,20 +184,23 @@ module Dependabot
|
|
150
184
|
files.each do |file|
|
151
185
|
path = file.name
|
152
186
|
FileUtils.mkdir_p(Pathname.new(path).dirname)
|
153
|
-
File.write(path, sanitize_mixfile(file.content))
|
187
|
+
File.write(path, sanitize_mixfile(T.must(file.content)))
|
154
188
|
end
|
155
189
|
end
|
156
190
|
|
191
|
+
sig { params(content: String).returns(String) }
|
157
192
|
def sanitize_mixfile(content)
|
158
193
|
Hex::FileUpdater::MixfileSanitizer.new(
|
159
194
|
mixfile_content: content
|
160
195
|
).sanitized_content
|
161
196
|
end
|
162
197
|
|
198
|
+
sig { returns(T.class_of(Dependabot::Version)) }
|
163
199
|
def version_class
|
164
200
|
dependency.version_class
|
165
201
|
end
|
166
202
|
|
203
|
+
sig { returns(T::Hash[String, String]) }
|
167
204
|
def mix_env
|
168
205
|
{
|
169
206
|
"MIX_EXS" => File.join(NativeHelpers.hex_helpers_dir, "mix.exs"),
|
@@ -171,10 +208,12 @@ module Dependabot
|
|
171
208
|
}
|
172
209
|
end
|
173
210
|
|
211
|
+
sig { returns(String) }
|
174
212
|
def elixir_helper_path
|
175
213
|
File.join(NativeHelpers.hex_helpers_dir, "lib/run.exs")
|
176
214
|
end
|
177
215
|
|
216
|
+
sig { returns(String) }
|
178
217
|
def elixir_helper_check_update_path
|
179
218
|
File.join(NativeHelpers.hex_helpers_dir, "lib/check_update.exs")
|
180
219
|
end
|
@@ -13,6 +13,7 @@ module Dependabot
|
|
13
13
|
module Hex
|
14
14
|
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
15
15
|
extend T::Sig
|
16
|
+
|
16
17
|
require_relative "update_checker/file_preparer"
|
17
18
|
require_relative "update_checker/requirements_updater"
|
18
19
|
require_relative "update_checker/version_resolver"
|
@@ -20,26 +21,26 @@ module Dependabot
|
|
20
21
|
|
21
22
|
sig { override.returns(T.nilable(T.any(String, Dependabot::Version, Gem::Version))) }
|
22
23
|
def latest_version
|
23
|
-
@latest_version
|
24
|
-
|
25
|
-
@latest_version ||=
|
24
|
+
@latest_version ||= T.let(
|
26
25
|
if git_dependency?
|
27
26
|
latest_version_for_git_dependency
|
28
27
|
else
|
29
28
|
latest_release_from_hex_registry || latest_resolvable_version
|
30
|
-
end
|
29
|
+
end,
|
30
|
+
T.nilable(T.any(String, Dependabot::Version, Gem::Version))
|
31
|
+
)
|
31
32
|
end
|
32
33
|
|
33
34
|
sig { override.returns(T.nilable(T.any(String, Dependabot::Version, Gem::Version))) }
|
34
35
|
def latest_resolvable_version
|
35
|
-
@latest_resolvable_version
|
36
|
-
|
37
|
-
@latest_resolvable_version ||=
|
36
|
+
@latest_resolvable_version ||= T.let(
|
38
37
|
if git_dependency?
|
39
38
|
latest_resolvable_version_for_git_dependency
|
40
39
|
else
|
41
40
|
fetch_latest_resolvable_version(unlock_requirement: true)
|
42
|
-
end
|
41
|
+
end,
|
42
|
+
T.nilable(T.any(String, Dependabot::Version, Gem::Version))
|
43
|
+
)
|
43
44
|
end
|
44
45
|
|
45
46
|
sig { override.returns(T.any(String, T.nilable(Dependabot::Version))) }
|
@@ -157,11 +158,13 @@ module Dependabot
|
|
157
158
|
).latest_resolvable_version
|
158
159
|
|
159
160
|
@git_tag_resolvable = !resolver_result.nil?
|
161
|
+
@git_tag_resolvable
|
160
162
|
rescue SharedHelpers::HelperSubprocessFailed,
|
161
163
|
Dependabot::DependencyFileNotResolvable => e
|
162
164
|
raise e unless e.message.include?("resolution failed")
|
163
165
|
|
164
166
|
@git_tag_resolvable = T.let(false, T.nilable(T::Boolean))
|
167
|
+
false
|
165
168
|
end
|
166
169
|
|
167
170
|
sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
|
@@ -247,13 +250,13 @@ module Dependabot
|
|
247
250
|
|
248
251
|
sig { returns(Dependabot::GitCommitChecker) }
|
249
252
|
def git_commit_checker
|
250
|
-
@git_commit_checker
|
251
|
-
|
252
|
-
@git_commit_checker ||=
|
253
|
+
@git_commit_checker ||= T.let(
|
253
254
|
GitCommitChecker.new(
|
254
255
|
dependency: dependency,
|
255
256
|
credentials: credentials
|
256
|
-
)
|
257
|
+
),
|
258
|
+
T.nilable(Dependabot::GitCommitChecker)
|
259
|
+
)
|
257
260
|
end
|
258
261
|
end
|
259
262
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "sorbet-runtime"
|
@@ -15,33 +15,40 @@ module Dependabot
|
|
15
15
|
class Version < Dependabot::Version
|
16
16
|
extend T::Sig
|
17
17
|
|
18
|
+
sig { returns(T.nilable(String)) }
|
18
19
|
attr_reader :build_info
|
19
20
|
|
20
|
-
VERSION_PATTERN = Gem::Version::VERSION_PATTERN + '(\+[0-9a-zA-Z\-.]+)?'
|
21
|
-
ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z
|
21
|
+
VERSION_PATTERN = T.let(Gem::Version::VERSION_PATTERN + '(\+[0-9a-zA-Z\-.]+)?', String)
|
22
|
+
ANCHORED_VERSION_PATTERN = T.let(/\A\s*(#{VERSION_PATTERN})?\s*\z/, Regexp)
|
22
23
|
|
24
|
+
sig { override.params(version: VersionParameter).returns(T::Boolean) }
|
23
25
|
def self.correct?(version)
|
24
26
|
return false if version.nil?
|
25
27
|
|
26
28
|
version.to_s.match?(ANCHORED_VERSION_PATTERN)
|
27
29
|
end
|
28
30
|
|
31
|
+
sig { override.params(version: VersionParameter).void }
|
29
32
|
def initialize(version)
|
30
|
-
@version_string = version.to_s
|
33
|
+
@version_string = T.let(version.to_s, String)
|
31
34
|
|
32
35
|
version, @build_info = version.to_s.split("+") if version.to_s.include?("+")
|
36
|
+
@build_info = T.let(@build_info, T.nilable(String))
|
33
37
|
|
34
38
|
super
|
35
39
|
end
|
36
40
|
|
41
|
+
sig { override.returns(String) }
|
37
42
|
def to_s
|
38
43
|
@version_string
|
39
44
|
end
|
40
45
|
|
46
|
+
sig { override.returns(String) }
|
41
47
|
def inspect # :nodoc:
|
42
48
|
"#<#{self.class} #{@version_string}>"
|
43
49
|
end
|
44
50
|
|
51
|
+
sig { params(other: T.untyped).returns(T.nilable(Integer)) }
|
45
52
|
def <=>(other)
|
46
53
|
version_comparison = super
|
47
54
|
return version_comparison unless version_comparison&.zero?
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dependabot-hex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.333.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.333.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.333.0
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: debug
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -211,14 +211,14 @@ dependencies:
|
|
211
211
|
requirements:
|
212
212
|
- - "~>"
|
213
213
|
- !ruby/object:Gem::Version
|
214
|
-
version: '3.
|
214
|
+
version: '3.25'
|
215
215
|
type: :development
|
216
216
|
prerelease: false
|
217
217
|
version_requirements: !ruby/object:Gem::Requirement
|
218
218
|
requirements:
|
219
219
|
- - "~>"
|
220
220
|
- !ruby/object:Gem::Version
|
221
|
-
version: '3.
|
221
|
+
version: '3.25'
|
222
222
|
- !ruby/object:Gem::Dependency
|
223
223
|
name: webrick
|
224
224
|
requirement: !ruby/object:Gem::Requirement
|
@@ -274,7 +274,7 @@ licenses:
|
|
274
274
|
- MIT
|
275
275
|
metadata:
|
276
276
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
277
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
277
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.333.0
|
278
278
|
rdoc_options: []
|
279
279
|
require_paths:
|
280
280
|
- lib
|