dependabot-elm 0.82.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/dependabot/elm/file_fetcher.rb +53 -0
- data/lib/dependabot/elm/file_parser.rb +137 -0
- data/lib/dependabot/elm/file_updater.rb +80 -0
- data/lib/dependabot/elm/file_updater/elm_json_updater.rb +67 -0
- data/lib/dependabot/elm/file_updater/elm_package_updater.rb +67 -0
- data/lib/dependabot/elm/metadata_finder.rb +24 -0
- data/lib/dependabot/elm/requirement.rb +94 -0
- data/lib/dependabot/elm/update_checker.rb +128 -0
- data/lib/dependabot/elm/update_checker/cli_parser.rb +31 -0
- data/lib/dependabot/elm/update_checker/elm_18_version_resolver.rb +232 -0
- data/lib/dependabot/elm/update_checker/elm_19_version_resolver.rb +196 -0
- data/lib/dependabot/elm/update_checker/requirements_updater.rb +73 -0
- data/lib/dependabot/elm/version.rb +22 -0
- metadata +183 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "excon"
|
4
|
+
require "dependabot/update_checkers"
|
5
|
+
require "dependabot/update_checkers/base"
|
6
|
+
require "dependabot/shared_helpers"
|
7
|
+
require "dependabot/errors"
|
8
|
+
|
9
|
+
module Dependabot
|
10
|
+
module Elm
|
11
|
+
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
12
|
+
require_relative "update_checker/requirements_updater"
|
13
|
+
require_relative "update_checker/elm_18_version_resolver"
|
14
|
+
require_relative "update_checker/elm_19_version_resolver"
|
15
|
+
|
16
|
+
def latest_version
|
17
|
+
@latest_version ||= candidate_versions.max
|
18
|
+
end
|
19
|
+
|
20
|
+
# Overwrite the base class to allow multi-dependency update PRs for
|
21
|
+
# dependencies for which we don't have a version.
|
22
|
+
def can_update?(requirements_to_unlock:)
|
23
|
+
if dependency.appears_in_lockfile?
|
24
|
+
version_can_update?(requirements_to_unlock: requirements_to_unlock)
|
25
|
+
elsif requirements_to_unlock == :none
|
26
|
+
false
|
27
|
+
elsif requirements_to_unlock == :own
|
28
|
+
requirements_can_update?
|
29
|
+
elsif requirements_to_unlock == :all
|
30
|
+
updated_dependencies_after_full_unlock.any?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def latest_resolvable_version
|
35
|
+
@latest_resolvable_version ||=
|
36
|
+
version_resolver.
|
37
|
+
latest_resolvable_version(unlock_requirement: :own)
|
38
|
+
end
|
39
|
+
|
40
|
+
def latest_resolvable_version_with_no_unlock
|
41
|
+
# Irrelevant, since Elm has a single dependency file (well, there's
|
42
|
+
# also `exact-dependencies.json`, but it's not recommended that that
|
43
|
+
# is committed).
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def updated_requirements
|
48
|
+
RequirementsUpdater.new(
|
49
|
+
requirements: dependency.requirements,
|
50
|
+
latest_resolvable_version: latest_resolvable_version
|
51
|
+
).updated_requirements
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def version_resolver
|
57
|
+
@version_resolver ||=
|
58
|
+
if dependency.requirements.any? { |r| r.fetch(:file) == "elm.json" }
|
59
|
+
Elm19VersionResolver.new(
|
60
|
+
dependency: dependency,
|
61
|
+
dependency_files: dependency_files
|
62
|
+
)
|
63
|
+
else
|
64
|
+
Elm18VersionResolver.new(
|
65
|
+
dependency: dependency,
|
66
|
+
dependency_files: dependency_files,
|
67
|
+
candidate_versions: candidate_versions
|
68
|
+
)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def updated_dependencies_after_full_unlock
|
73
|
+
version_resolver.updated_dependencies_after_full_unlock
|
74
|
+
end
|
75
|
+
|
76
|
+
def latest_version_resolvable_with_full_unlock?
|
77
|
+
latest_version == version_resolver.
|
78
|
+
latest_resolvable_version(unlock_requirement: :all)
|
79
|
+
end
|
80
|
+
|
81
|
+
def candidate_versions
|
82
|
+
all_versions.
|
83
|
+
reject { |v| ignore_reqs.any? { |r| r.satisfied_by?(v) } }
|
84
|
+
end
|
85
|
+
|
86
|
+
def all_versions
|
87
|
+
return @all_versions if @version_lookup_attempted
|
88
|
+
|
89
|
+
@version_lookup_attempted = true
|
90
|
+
|
91
|
+
response = Excon.get(
|
92
|
+
"https://package.elm-lang.org/packages/#{dependency.name}/"\
|
93
|
+
"releases.json",
|
94
|
+
idempotent: true,
|
95
|
+
**Dependabot::SharedHelpers.excon_defaults
|
96
|
+
)
|
97
|
+
|
98
|
+
return @all_versions = [] unless response.status == 200
|
99
|
+
|
100
|
+
@all_versions =
|
101
|
+
JSON.parse(response.body).
|
102
|
+
keys.
|
103
|
+
map { |v| version_class.new(v) }.
|
104
|
+
sort
|
105
|
+
end
|
106
|
+
|
107
|
+
# Overwrite the base class's requirements_up_to_date? method to instead
|
108
|
+
# check whether the latest version is allowed
|
109
|
+
def requirements_up_to_date?
|
110
|
+
return false unless latest_version
|
111
|
+
|
112
|
+
dependency.requirements.
|
113
|
+
map { |r| r.fetch(:requirement) }.
|
114
|
+
map { |r| requirement_class.new(r) }.
|
115
|
+
all? { |r| r.satisfied_by?(latest_version) }
|
116
|
+
end
|
117
|
+
|
118
|
+
def ignore_reqs
|
119
|
+
# Note: we use Gem::Requirement here because ignore conditions will
|
120
|
+
# be passed as Ruby ranges
|
121
|
+
ignored_versions.map { |req| Gem::Requirement.new(req.split(",")) }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
Dependabot::UpdateCheckers.
|
128
|
+
register("elm-package", Dependabot::Elm::UpdateChecker)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dependabot/elm/version"
|
4
|
+
require "dependabot/elm/update_checker"
|
5
|
+
|
6
|
+
module Dependabot
|
7
|
+
module Elm
|
8
|
+
class UpdateChecker
|
9
|
+
class CliParser
|
10
|
+
INSTALL_DEPENDENCY_REGEX =
|
11
|
+
%r{([^\s]+\/[^\s]+)\s+(\d+\.\d+\.\d+)}.freeze
|
12
|
+
UPGRADE_DEPENDENCY_REGEX =
|
13
|
+
%r{([^\s]+\/[^\s]+) \(\d+\.\d+\.\d+ => (\d+\.\d+\.\d+)\)}.freeze
|
14
|
+
|
15
|
+
def self.decode_install_preview(text)
|
16
|
+
installs = {}
|
17
|
+
|
18
|
+
# Parse new installs
|
19
|
+
text.scan(INSTALL_DEPENDENCY_REGEX).
|
20
|
+
each { |n, v| installs[n] = Elm::Version.new(v) }
|
21
|
+
|
22
|
+
# Parse upgrades
|
23
|
+
text.scan(UPGRADE_DEPENDENCY_REGEX).
|
24
|
+
each { |n, v| installs[n] = Elm::Version.new(v) }
|
25
|
+
|
26
|
+
installs
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dependabot/shared_helpers"
|
4
|
+
require "dependabot/errors"
|
5
|
+
require "dependabot/elm/file_parser"
|
6
|
+
require "dependabot/elm/update_checker"
|
7
|
+
require "dependabot/elm/update_checker/cli_parser"
|
8
|
+
require "dependabot/elm/update_checker/requirements_updater"
|
9
|
+
require "dependabot/elm/requirement"
|
10
|
+
|
11
|
+
module Dependabot
|
12
|
+
module Elm
|
13
|
+
class UpdateChecker
|
14
|
+
class Elm18VersionResolver
|
15
|
+
class UnrecoverableState < StandardError; end
|
16
|
+
|
17
|
+
def initialize(dependency:, dependency_files:, candidate_versions:)
|
18
|
+
@dependency = dependency
|
19
|
+
@dependency_files = dependency_files
|
20
|
+
@candidate_versions = candidate_versions
|
21
|
+
end
|
22
|
+
|
23
|
+
def latest_resolvable_version(unlock_requirement:)
|
24
|
+
unless %i(none own all).include?(unlock_requirement)
|
25
|
+
raise "Invalid unlock setting: #{unlock_requirement}"
|
26
|
+
end
|
27
|
+
|
28
|
+
# Elm has no lockfile, so we will never create an update PR if
|
29
|
+
# unlock requirements are `none`. Just return the current version.
|
30
|
+
return current_version if unlock_requirement == :none
|
31
|
+
|
32
|
+
# Otherwise, we gotta check a few conditions to see if bumping
|
33
|
+
# wouldn't also bump other deps in elm-package.json
|
34
|
+
candidate_versions.sort.reverse_each do |version|
|
35
|
+
return version if can_update?(version, unlock_requirement)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Fall back to returning the dependency's current version, which is
|
39
|
+
# presumed to be resolvable
|
40
|
+
current_version
|
41
|
+
end
|
42
|
+
|
43
|
+
def updated_dependencies_after_full_unlock
|
44
|
+
version = latest_resolvable_version(unlock_requirement: :all)
|
45
|
+
deps_after_install = fetch_install_metadata(target_version: version)
|
46
|
+
|
47
|
+
original_dependency_details.map do |original_dep|
|
48
|
+
new_version = deps_after_install.fetch(original_dep.name)
|
49
|
+
|
50
|
+
old_reqs = original_dep.requirements.map do |req|
|
51
|
+
requirement_class.new(req[:requirement])
|
52
|
+
end
|
53
|
+
|
54
|
+
next if old_reqs.all? { |req| req.satisfied_by?(new_version) }
|
55
|
+
|
56
|
+
new_requirements =
|
57
|
+
RequirementsUpdater.new(
|
58
|
+
requirements: original_dep.requirements,
|
59
|
+
latest_resolvable_version: new_version.to_s
|
60
|
+
).updated_requirements
|
61
|
+
|
62
|
+
Dependency.new(
|
63
|
+
name: original_dep.name,
|
64
|
+
version: new_version.to_s,
|
65
|
+
requirements: new_requirements,
|
66
|
+
previous_version: original_dep.version,
|
67
|
+
previous_requirements: original_dep.requirements,
|
68
|
+
package_manager: original_dep.package_manager
|
69
|
+
)
|
70
|
+
end.compact
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
attr_reader :dependency, :dependency_files, :candidate_versions
|
76
|
+
|
77
|
+
def can_update?(version, unlock_requirement)
|
78
|
+
deps_after_install = fetch_install_metadata(target_version: version)
|
79
|
+
|
80
|
+
result = check_install_result(deps_after_install, version)
|
81
|
+
|
82
|
+
# If the install was clean then we can definitely update
|
83
|
+
return true if result == :clean_bump
|
84
|
+
|
85
|
+
# Otherwise, we can still update if the result was a forced full
|
86
|
+
# unlock and we're allowed to unlock other requirements
|
87
|
+
return false unless unlock_requirement == :all
|
88
|
+
|
89
|
+
result == :forced_full_unlock_bump
|
90
|
+
end
|
91
|
+
|
92
|
+
def check_install_result(deps_after_install, target_version)
|
93
|
+
# This can go one of 5 ways:
|
94
|
+
# 1) We bump our dep and no other dep is bumped
|
95
|
+
# 2) We bump our dep and another dep is bumped too
|
96
|
+
# Scenario: NoRedInk/datetimepicker bump to 3.0.2 also
|
97
|
+
# bumps elm-css to 14
|
98
|
+
# 3) We bump our dep but actually elm-package doesn't bump it
|
99
|
+
# Scenario: elm-css bump to 14 but datetimepicker is at 3.0.1
|
100
|
+
# 4) We bump our dep but elm-package just says
|
101
|
+
# "Packages configured successfully!"
|
102
|
+
# Narrator: they weren't
|
103
|
+
# Scenario: impossible dependency (i.e. elm-css 999.999.999)
|
104
|
+
# a <= v < b where a is greater than latest version
|
105
|
+
# 5) We bump our dep but elm-package blows up (not handled here)
|
106
|
+
# Scenario: rtfeldman/elm-css 14 && rtfeldman/hashed-class 1.0.0
|
107
|
+
# I'm not sure what's different from this scenario
|
108
|
+
# to 3), why it blows up instead of just rolling
|
109
|
+
# elm-css back to version 9 which is what
|
110
|
+
# hashed-class requires
|
111
|
+
|
112
|
+
# 4) We bump our dep but elm-package just says
|
113
|
+
# "Packages configured successfully!"
|
114
|
+
return :empty_elm_stuff_bug if deps_after_install.empty?
|
115
|
+
|
116
|
+
version_after_install = deps_after_install.fetch(dependency.name)
|
117
|
+
|
118
|
+
# 3) We bump our dep but actually elm-package doesn't bump it
|
119
|
+
return :downgrade_bug if version_after_install < target_version
|
120
|
+
|
121
|
+
other_top_level_deps_bumped =
|
122
|
+
original_dependency_details.
|
123
|
+
reject { |dep| dep.name == dependency.name }.
|
124
|
+
select do |dep|
|
125
|
+
reqs = dep.requirements.map { |r| r.fetch(:requirement) }
|
126
|
+
reqs = reqs.map { |r| requirement_class.new(r) }
|
127
|
+
reqs.any? { |r| !r.satisfied_by?(deps_after_install[dep.name]) }
|
128
|
+
end
|
129
|
+
|
130
|
+
# 2) We bump our dep and another dep is bumped
|
131
|
+
return :forced_full_unlock_bump if other_top_level_deps_bumped.any?
|
132
|
+
|
133
|
+
# 1) We bump our dep and no other dep is bumped
|
134
|
+
:clean_bump
|
135
|
+
end
|
136
|
+
|
137
|
+
def fetch_install_metadata(target_version:)
|
138
|
+
@install_cache ||= {}
|
139
|
+
@install_cache[target_version.to_s] ||=
|
140
|
+
SharedHelpers.in_a_temporary_directory do
|
141
|
+
write_temporary_dependency_files(target_version: target_version)
|
142
|
+
|
143
|
+
# Elm package install outputs a preview of the actions to be
|
144
|
+
# performed. We can use this preview to calculate whether it
|
145
|
+
# would do anything funny
|
146
|
+
command = "yes n | elm-package install"
|
147
|
+
response = run_shell_command(command)
|
148
|
+
|
149
|
+
deps_after_install = CliParser.decode_install_preview(response)
|
150
|
+
|
151
|
+
deps_after_install
|
152
|
+
rescue SharedHelpers::HelperSubprocessFailed => error
|
153
|
+
# 5) We bump our dep but elm-package blows up
|
154
|
+
handle_elm_package_errors(error)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def run_shell_command(command)
|
159
|
+
raw_response = nil
|
160
|
+
IO.popen(command, err: %i(child out)) do |process|
|
161
|
+
raw_response = process.read
|
162
|
+
end
|
163
|
+
|
164
|
+
# Raise an error with the output from the shell session if Elm
|
165
|
+
# returns a non-zero status
|
166
|
+
return raw_response if $CHILD_STATUS.success?
|
167
|
+
|
168
|
+
raise SharedHelpers::HelperSubprocessFailed.new(
|
169
|
+
raw_response,
|
170
|
+
command
|
171
|
+
)
|
172
|
+
end
|
173
|
+
|
174
|
+
def handle_elm_package_errors(error)
|
175
|
+
if error.message.include?("I cannot find a set of packages that " \
|
176
|
+
"works with your constraints")
|
177
|
+
raise Dependabot::DependencyFileNotResolvable, error.message
|
178
|
+
end
|
179
|
+
|
180
|
+
# I don't know any other errors
|
181
|
+
raise error
|
182
|
+
end
|
183
|
+
|
184
|
+
def write_temporary_dependency_files(target_version:)
|
185
|
+
dependency_files.each do |file|
|
186
|
+
path = file.name
|
187
|
+
FileUtils.mkdir_p(Pathname.new(path).dirname)
|
188
|
+
|
189
|
+
File.write(
|
190
|
+
path,
|
191
|
+
updated_elm_package_content(file.content, target_version)
|
192
|
+
)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def updated_elm_package_content(content, version)
|
197
|
+
json = JSON.parse(content)
|
198
|
+
|
199
|
+
new_requirement = RequirementsUpdater.new(
|
200
|
+
requirements: dependency.requirements,
|
201
|
+
latest_resolvable_version: version.to_s
|
202
|
+
).updated_requirements.first[:requirement]
|
203
|
+
|
204
|
+
json["dependencies"][dependency.name] = new_requirement
|
205
|
+
JSON.dump(json)
|
206
|
+
end
|
207
|
+
|
208
|
+
def original_dependency_details
|
209
|
+
@original_dependency_details ||=
|
210
|
+
Elm::FileParser.new(
|
211
|
+
dependency_files: dependency_files,
|
212
|
+
source: nil
|
213
|
+
).parse
|
214
|
+
end
|
215
|
+
|
216
|
+
def current_version
|
217
|
+
return unless dependency.version
|
218
|
+
|
219
|
+
version_class.new(dependency.version)
|
220
|
+
end
|
221
|
+
|
222
|
+
def version_class
|
223
|
+
Elm::Version
|
224
|
+
end
|
225
|
+
|
226
|
+
def requirement_class
|
227
|
+
Elm::Requirement
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dependabot/shared_helpers"
|
4
|
+
require "dependabot/errors"
|
5
|
+
require "dependabot/elm/file_parser"
|
6
|
+
require "dependabot/elm/update_checker"
|
7
|
+
require "dependabot/elm/update_checker/cli_parser"
|
8
|
+
require "dependabot/elm/update_checker/requirements_updater"
|
9
|
+
require "dependabot/elm/requirement"
|
10
|
+
|
11
|
+
module Dependabot
|
12
|
+
module Elm
|
13
|
+
class UpdateChecker
|
14
|
+
class Elm19VersionResolver
|
15
|
+
class UnrecoverableState < StandardError; end
|
16
|
+
|
17
|
+
def initialize(dependency:, dependency_files:)
|
18
|
+
@dependency = dependency
|
19
|
+
@dependency_files = dependency_files
|
20
|
+
end
|
21
|
+
|
22
|
+
def latest_resolvable_version(unlock_requirement:)
|
23
|
+
unless %i(none own all).include?(unlock_requirement)
|
24
|
+
raise "Invalid unlock setting: #{unlock_requirement}"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Elm has no lockfile, so we will never create an update PR if
|
28
|
+
# unlock requirements are `none`. Just return the current version.
|
29
|
+
return current_version if unlock_requirement == :none
|
30
|
+
|
31
|
+
# Otherwise, we gotta check a few conditions to see if bumping
|
32
|
+
# wouldn't also bump other deps in elm-package.json
|
33
|
+
fetch_latest_resolvable_version(unlock_requirement)
|
34
|
+
end
|
35
|
+
|
36
|
+
def updated_dependencies_after_full_unlock
|
37
|
+
changed_deps = install_metadata
|
38
|
+
|
39
|
+
original_dependency_details.map do |original_dep|
|
40
|
+
new_version = changed_deps.fetch(original_dep.name, nil)
|
41
|
+
next unless new_version
|
42
|
+
|
43
|
+
old_reqs = original_dep.requirements.map do |req|
|
44
|
+
requirement_class.new(req[:requirement])
|
45
|
+
end
|
46
|
+
|
47
|
+
next if old_reqs.all? { |req| req.satisfied_by?(new_version) }
|
48
|
+
|
49
|
+
new_requirements =
|
50
|
+
RequirementsUpdater.new(
|
51
|
+
requirements: original_dep.requirements,
|
52
|
+
latest_resolvable_version: new_version.to_s
|
53
|
+
).updated_requirements
|
54
|
+
|
55
|
+
Dependency.new(
|
56
|
+
name: original_dep.name,
|
57
|
+
version: new_version.to_s,
|
58
|
+
requirements: new_requirements,
|
59
|
+
previous_version: original_dep.version,
|
60
|
+
previous_requirements: original_dep.requirements,
|
61
|
+
package_manager: original_dep.package_manager
|
62
|
+
)
|
63
|
+
end.compact
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
attr_reader :dependency, :dependency_files
|
69
|
+
|
70
|
+
def fetch_latest_resolvable_version(unlock_requirement)
|
71
|
+
changed_deps = install_metadata
|
72
|
+
|
73
|
+
result = check_install_result(changed_deps)
|
74
|
+
version_after_install = changed_deps.fetch(dependency.name)
|
75
|
+
|
76
|
+
# If the install was clean then we can definitely update
|
77
|
+
return version_after_install if result == :clean_bump
|
78
|
+
|
79
|
+
# Otherwise, we can still update if the result was a forced full
|
80
|
+
# unlock and we're allowed to unlock other requirements
|
81
|
+
return version_after_install if unlock_requirement == :all
|
82
|
+
|
83
|
+
current_version
|
84
|
+
end
|
85
|
+
|
86
|
+
def check_install_result(changed_deps)
|
87
|
+
other_deps_bumped =
|
88
|
+
changed_deps.
|
89
|
+
keys.
|
90
|
+
reject { |name| name == dependency.name }
|
91
|
+
|
92
|
+
return :forced_full_unlock_bump if other_deps_bumped.any?
|
93
|
+
|
94
|
+
:clean_bump
|
95
|
+
end
|
96
|
+
|
97
|
+
def install_metadata
|
98
|
+
@install_metadata ||=
|
99
|
+
SharedHelpers.in_a_temporary_directory do
|
100
|
+
write_temporary_dependency_files
|
101
|
+
|
102
|
+
# Elm package install outputs a preview of the actions to be
|
103
|
+
# performed. We can use this preview to calculate whether it
|
104
|
+
# would do anything funny
|
105
|
+
command = "yes n | elm19 install #{dependency.name}"
|
106
|
+
response = run_shell_command(command)
|
107
|
+
|
108
|
+
CliParser.decode_install_preview(response)
|
109
|
+
rescue SharedHelpers::HelperSubprocessFailed => error
|
110
|
+
# 5) We bump our dep but elm blows up
|
111
|
+
handle_elm_errors(error)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def run_shell_command(command)
|
116
|
+
raw_response = nil
|
117
|
+
IO.popen(command, err: %i(child out)) do |process|
|
118
|
+
raw_response = process.read
|
119
|
+
end
|
120
|
+
|
121
|
+
# Raise an error with the output from the shell session if Elm
|
122
|
+
# returns a non-zero status
|
123
|
+
return raw_response if $CHILD_STATUS.success?
|
124
|
+
|
125
|
+
raise SharedHelpers::HelperSubprocessFailed.new(
|
126
|
+
raw_response,
|
127
|
+
command
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
def handle_elm_errors(error)
|
132
|
+
if error.message.include?("OLD DEPENDENCIES") ||
|
133
|
+
error.message.include?("BAD JSON")
|
134
|
+
raise Dependabot::DependencyFileNotResolvable, error.message
|
135
|
+
end
|
136
|
+
|
137
|
+
# Raise any unrecognised errors
|
138
|
+
raise error
|
139
|
+
end
|
140
|
+
|
141
|
+
def write_temporary_dependency_files
|
142
|
+
dependency_files.each do |file|
|
143
|
+
path = file.name
|
144
|
+
FileUtils.mkdir_p(Pathname.new(path).dirname)
|
145
|
+
|
146
|
+
File.write(path, updated_elm_json_content(file.content))
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def updated_elm_json_content(content)
|
151
|
+
json = JSON.parse(content)
|
152
|
+
|
153
|
+
# Delete the dependency from the elm.json, so that we can use
|
154
|
+
# `elm install <dependency_name>` to generate the install plan
|
155
|
+
%w(dependencies test-dependencies).each do |type|
|
156
|
+
if json.dig(type, dependency.name)
|
157
|
+
json[type].delete(dependency.name)
|
158
|
+
end
|
159
|
+
|
160
|
+
%w(direct indirect).each do |category|
|
161
|
+
if json.dig(type, category, dependency.name)
|
162
|
+
json[type][category].delete(dependency.name)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
json["source-directories"] = []
|
168
|
+
|
169
|
+
JSON.dump(json)
|
170
|
+
end
|
171
|
+
|
172
|
+
def original_dependency_details
|
173
|
+
@original_dependency_details ||=
|
174
|
+
Elm::FileParser.new(
|
175
|
+
dependency_files: dependency_files,
|
176
|
+
source: nil
|
177
|
+
).parse
|
178
|
+
end
|
179
|
+
|
180
|
+
def current_version
|
181
|
+
return unless dependency.version
|
182
|
+
|
183
|
+
version_class.new(dependency.version)
|
184
|
+
end
|
185
|
+
|
186
|
+
def version_class
|
187
|
+
Elm::Version
|
188
|
+
end
|
189
|
+
|
190
|
+
def requirement_class
|
191
|
+
Elm::Requirement
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|