dependabot-hex 0.88.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 +7 -0
- data/helpers/build +19 -0
- data/helpers/deps/jason/.fetch +0 -0
- data/helpers/deps/jason/.hex +2 -0
- data/helpers/deps/jason/CHANGELOG.md +60 -0
- data/helpers/deps/jason/LICENSE +13 -0
- data/helpers/deps/jason/README.md +179 -0
- data/helpers/deps/jason/hex_metadata.config +20 -0
- data/helpers/deps/jason/lib/codegen.ex +158 -0
- data/helpers/deps/jason/lib/decoder.ex +657 -0
- data/helpers/deps/jason/lib/encode.ex +630 -0
- data/helpers/deps/jason/lib/encoder.ex +216 -0
- data/helpers/deps/jason/lib/formatter.ex +253 -0
- data/helpers/deps/jason/lib/fragment.ex +11 -0
- data/helpers/deps/jason/lib/helpers.ex +90 -0
- data/helpers/deps/jason/lib/jason.ex +228 -0
- data/helpers/deps/jason/mix.exs +92 -0
- data/helpers/lib/check_update.exs +92 -0
- data/helpers/lib/do_update.exs +39 -0
- data/helpers/lib/parse_deps.exs +103 -0
- data/helpers/lib/run.exs +76 -0
- data/helpers/mix.exs +21 -0
- data/helpers/mix.lock +3 -0
- data/lib/dependabot/hex.rb +11 -0
- data/lib/dependabot/hex/file_fetcher.rb +79 -0
- data/lib/dependabot/hex/file_parser.rb +125 -0
- data/lib/dependabot/hex/file_updater.rb +71 -0
- data/lib/dependabot/hex/file_updater/lockfile_updater.rb +142 -0
- data/lib/dependabot/hex/file_updater/mixfile_git_pin_updater.rb +51 -0
- data/lib/dependabot/hex/file_updater/mixfile_requirement_updater.rb +72 -0
- data/lib/dependabot/hex/file_updater/mixfile_sanitizer.rb +26 -0
- data/lib/dependabot/hex/file_updater/mixfile_updater.rb +94 -0
- data/lib/dependabot/hex/metadata_finder.rb +70 -0
- data/lib/dependabot/hex/native_helpers.rb +20 -0
- data/lib/dependabot/hex/requirement.rb +53 -0
- data/lib/dependabot/hex/update_checker.rb +275 -0
- data/lib/dependabot/hex/update_checker/file_preparer.rb +191 -0
- data/lib/dependabot/hex/update_checker/requirements_updater.rb +173 -0
- data/lib/dependabot/hex/update_checker/version_resolver.rb +170 -0
- data/lib/dependabot/hex/version.rb +67 -0
- metadata +208 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[dependency_name | credentials] = System.argv()
|
|
2
|
+
|
|
3
|
+
grouped_creds = Enum.reduce credentials, [], fn cred, acc ->
|
|
4
|
+
if List.last(acc) == nil || List.last(acc)[:token] do
|
|
5
|
+
List.insert_at(acc, -1, %{ organization: cred })
|
|
6
|
+
else
|
|
7
|
+
{ item, acc } = List.pop_at(acc, -1)
|
|
8
|
+
item = Map.put(item, :token, cred)
|
|
9
|
+
List.insert_at(acc, -1, item)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
Enum.each grouped_creds, fn cred ->
|
|
14
|
+
hexpm = Hex.Repo.get_repo("hexpm")
|
|
15
|
+
repo = %{
|
|
16
|
+
url: hexpm.url <> "/repos/#{cred.organization}",
|
|
17
|
+
public_key: nil,
|
|
18
|
+
auth_key: cred.token
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
Hex.Config.read()
|
|
22
|
+
|> Hex.Config.read_repos()
|
|
23
|
+
|> Map.put("hexpm:#{cred.organization}", repo)
|
|
24
|
+
|> Hex.Config.update_repos()
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# dependency atom
|
|
28
|
+
dependency = String.to_atom(dependency_name)
|
|
29
|
+
|
|
30
|
+
# Fetch dependencies that needs updating
|
|
31
|
+
{dependency_lock, rest_lock} = Map.split(Mix.Dep.Lock.read(), [dependency])
|
|
32
|
+
Mix.Dep.Fetcher.by_name([dependency_name], dependency_lock, rest_lock, [])
|
|
33
|
+
|
|
34
|
+
lockfile_content =
|
|
35
|
+
"mix.lock"
|
|
36
|
+
|> File.read()
|
|
37
|
+
|> :erlang.term_to_binary()
|
|
38
|
+
|
|
39
|
+
IO.write(:stdio, lockfile_content)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
defmodule Parser do
|
|
2
|
+
def run do
|
|
3
|
+
Mix.Dep.load_on_environment([])
|
|
4
|
+
|> Enum.flat_map(&parse_dep/1)
|
|
5
|
+
|> Enum.map(&build_dependency(&1.opts[:lock], &1))
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
defp build_dependency(nil, dep) do
|
|
9
|
+
%{
|
|
10
|
+
name: dep.app,
|
|
11
|
+
from: Path.relative_to_cwd(dep.from),
|
|
12
|
+
groups: [],
|
|
13
|
+
requirement: normalise_requirement(dep.requirement),
|
|
14
|
+
top_level: dep.top_level || umbrella_top_level_dep?(dep)
|
|
15
|
+
}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
defp build_dependency(lock, dep) do
|
|
19
|
+
{version, checksum, source} = parse_lock(lock)
|
|
20
|
+
groups = parse_groups(dep.opts[:only])
|
|
21
|
+
|
|
22
|
+
%{
|
|
23
|
+
name: dep.app,
|
|
24
|
+
from: Path.relative_to_cwd(dep.from),
|
|
25
|
+
version: version,
|
|
26
|
+
groups: groups,
|
|
27
|
+
checksum: checksum,
|
|
28
|
+
requirement: normalise_requirement(dep.requirement),
|
|
29
|
+
source: source,
|
|
30
|
+
top_level: dep.top_level || umbrella_top_level_dep?(dep)
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
defp parse_groups(nil), do: []
|
|
35
|
+
defp parse_groups(only) when is_list(only), do: only
|
|
36
|
+
defp parse_groups(only), do: [only]
|
|
37
|
+
|
|
38
|
+
# path dependency
|
|
39
|
+
defp parse_dep(%{scm: Mix.SCM.Path, opts: opts} = dep) do
|
|
40
|
+
cond do
|
|
41
|
+
# umbrella dependency - ignore
|
|
42
|
+
opts[:in_umbrella] ->
|
|
43
|
+
[]
|
|
44
|
+
|
|
45
|
+
# umbrella application
|
|
46
|
+
opts[:from_umbrella] ->
|
|
47
|
+
Enum.reject(dep.deps, fn dep -> dep.opts[:in_umbrella] end)
|
|
48
|
+
|
|
49
|
+
true ->
|
|
50
|
+
[]
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# hex, git dependency
|
|
55
|
+
defp parse_dep(%{scm: scm} = dep) when scm in [Hex.SCM, Mix.SCM.Git], do: [dep]
|
|
56
|
+
|
|
57
|
+
# unsupported
|
|
58
|
+
defp parse_dep(_dep), do: []
|
|
59
|
+
|
|
60
|
+
defp umbrella_top_level_dep?(dep) do
|
|
61
|
+
if Mix.Project.umbrella?() do
|
|
62
|
+
apps_paths = Path.expand(Mix.Project.config()[:apps_path], File.cwd!())
|
|
63
|
+
String.contains?(Path.dirname(Path.dirname(dep.from)), apps_paths)
|
|
64
|
+
else
|
|
65
|
+
false
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
defp parse_lock({:git, repo_url, checksum, opts}),
|
|
70
|
+
do: {nil, checksum, git_source(repo_url, opts)}
|
|
71
|
+
|
|
72
|
+
defp parse_lock({:hex, _app, version, checksum, _managers, _dependencies, _source}),
|
|
73
|
+
do: {version, checksum, nil}
|
|
74
|
+
|
|
75
|
+
defp parse_lock({:hex, _app, version, checksum, _managers, _dependencies}),
|
|
76
|
+
do: {version, checksum, nil}
|
|
77
|
+
|
|
78
|
+
defp normalise_requirement(req) do
|
|
79
|
+
req
|
|
80
|
+
|> maybe_regex_to_str()
|
|
81
|
+
|> empty_str_to_nil()
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
defp maybe_regex_to_str(s), do: if Regex.regex?(s), do: Regex.source(s), else: s
|
|
85
|
+
defp empty_str_to_nil(""), do: nil
|
|
86
|
+
defp empty_str_to_nil(s), do: s
|
|
87
|
+
|
|
88
|
+
def git_source(repo_url, opts) do
|
|
89
|
+
ref = opts[:ref] || opts[:tag]
|
|
90
|
+
ref = if is_list(ref), do: to_string(ref), else: ref
|
|
91
|
+
|
|
92
|
+
%{
|
|
93
|
+
type: "git",
|
|
94
|
+
url: repo_url,
|
|
95
|
+
branch: opts[:branch] || "master",
|
|
96
|
+
ref: ref
|
|
97
|
+
}
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
dependencies = :erlang.term_to_binary({:ok, Parser.run()})
|
|
102
|
+
|
|
103
|
+
IO.write(:stdio, dependencies)
|
data/helpers/lib/run.exs
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
defmodule DependencyHelper do
|
|
2
|
+
def main() do
|
|
3
|
+
IO.read(:stdio, :all)
|
|
4
|
+
|> Jason.decode!()
|
|
5
|
+
|> run()
|
|
6
|
+
|> case do
|
|
7
|
+
{output, 0} ->
|
|
8
|
+
if output =~ "No authenticated organization found" do
|
|
9
|
+
{:error, output}
|
|
10
|
+
else
|
|
11
|
+
{:ok, :erlang.binary_to_term(output)}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
{error, 1} -> {:error, error}
|
|
15
|
+
end
|
|
16
|
+
|> handle_result()
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
defp handle_result({:ok, {:ok, result}}) do
|
|
20
|
+
encode_and_write(%{"result" => result})
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
defp handle_result({:ok, {:error, reason}}) do
|
|
24
|
+
encode_and_write(%{"error" => reason})
|
|
25
|
+
System.halt(1)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
defp handle_result({:error, reason}) do
|
|
29
|
+
encode_and_write(%{"error" => reason})
|
|
30
|
+
System.halt(1)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
defp encode_and_write(content) do
|
|
34
|
+
content
|
|
35
|
+
|> Jason.encode!()
|
|
36
|
+
|> IO.write()
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
defp run(%{"function" => "parse", "args" => [dir]}) do
|
|
40
|
+
run_script("parse_deps.exs", dir)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
defp run(%{"function" => "get_latest_resolvable_version", "args" => [dir, dependency_name, credentials]}) do
|
|
44
|
+
run_script("check_update.exs", dir, [dependency_name] ++ credentials)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
defp run(%{"function" => "get_updated_lockfile", "args" => [dir, dependency_name, credentials]}) do
|
|
48
|
+
run_script("do_update.exs", dir, [dependency_name] ++ credentials)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
defp run_script(script, dir, args \\ []) do
|
|
52
|
+
args = [
|
|
53
|
+
"run",
|
|
54
|
+
"--no-deps-check",
|
|
55
|
+
"--no-start",
|
|
56
|
+
"--no-compile",
|
|
57
|
+
"--no-elixir-version-check",
|
|
58
|
+
script
|
|
59
|
+
] ++ args
|
|
60
|
+
|
|
61
|
+
System.cmd(
|
|
62
|
+
"mix",
|
|
63
|
+
args,
|
|
64
|
+
[
|
|
65
|
+
cd: dir,
|
|
66
|
+
env: %{
|
|
67
|
+
"MIX_EXS" => nil,
|
|
68
|
+
"MIX_LOCK" => nil,
|
|
69
|
+
"MIX_DEPS" => nil
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
DependencyHelper.main()
|
data/helpers/mix.exs
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
defmodule DependabotCore.Mixfile do
|
|
2
|
+
use Mix.Project
|
|
3
|
+
|
|
4
|
+
def project do
|
|
5
|
+
[app: :dependabot_core,
|
|
6
|
+
version: "0.1.0",
|
|
7
|
+
elixir: "~> 1.5",
|
|
8
|
+
start_permanent: Mix.env == :prod,
|
|
9
|
+
lockfile: System.get_env("MIX_LOCK") || "mix.lock",
|
|
10
|
+
deps_path: System.get_env("MIX_DEPS") || "deps",
|
|
11
|
+
deps: deps()]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def application do
|
|
15
|
+
[extra_applications: [:logger]]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
defp deps() do
|
|
19
|
+
[{:jason, "~> 1.0-rc"}]
|
|
20
|
+
end
|
|
21
|
+
end
|
data/helpers/mix.lock
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# These all need to be required so the various classes can be registered in a
|
|
4
|
+
# lookup table of package manager names to concrete classes.
|
|
5
|
+
require "dependabot/hex/file_fetcher"
|
|
6
|
+
require "dependabot/hex/file_parser"
|
|
7
|
+
require "dependabot/hex/update_checker"
|
|
8
|
+
require "dependabot/hex/file_updater"
|
|
9
|
+
require "dependabot/hex/metadata_finder"
|
|
10
|
+
require "dependabot/hex/requirement"
|
|
11
|
+
require "dependabot/hex/version"
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dependabot/file_fetchers"
|
|
4
|
+
require "dependabot/file_fetchers/base"
|
|
5
|
+
|
|
6
|
+
module Dependabot
|
|
7
|
+
module Hex
|
|
8
|
+
class FileFetcher < Dependabot::FileFetchers::Base
|
|
9
|
+
APPS_PATH_REGEX = /apps_path:\s*"(?<path>.*?)"/m.freeze
|
|
10
|
+
STRING_ARG = %{(?:["'](.*?)["'])}
|
|
11
|
+
EVAL_FILE = /Code\.eval_file\(#{STRING_ARG}(?:\s*,\s*#{STRING_ARG})?\)/.
|
|
12
|
+
freeze
|
|
13
|
+
|
|
14
|
+
def self.required_files_in?(filenames)
|
|
15
|
+
filenames.include?("mix.exs")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.required_files_message
|
|
19
|
+
"Repo must contain a mix.exs."
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def fetch_files
|
|
25
|
+
fetched_files = []
|
|
26
|
+
fetched_files << mixfile
|
|
27
|
+
fetched_files << lockfile if lockfile
|
|
28
|
+
fetched_files += subapp_mixfiles
|
|
29
|
+
fetched_files += evaled_files
|
|
30
|
+
fetched_files
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def mixfile
|
|
34
|
+
@mixfile ||= fetch_file_from_host("mix.exs")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def lockfile
|
|
38
|
+
return @lockfile if @lockfile_lookup_attempted
|
|
39
|
+
|
|
40
|
+
@lockfile_lookup_attempted = true
|
|
41
|
+
@lockfile ||= fetch_file_from_host("mix.lock")
|
|
42
|
+
rescue Dependabot::DependencyFileNotFound
|
|
43
|
+
nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def subapp_mixfiles
|
|
47
|
+
apps_path = mixfile.content.match(APPS_PATH_REGEX)&.
|
|
48
|
+
named_captures&.fetch("path")
|
|
49
|
+
return [] unless apps_path
|
|
50
|
+
|
|
51
|
+
app_directories = repo_contents(dir: apps_path).
|
|
52
|
+
select { |f| f.type == "dir" }
|
|
53
|
+
|
|
54
|
+
app_directories.map do |dir|
|
|
55
|
+
fetch_file_from_host("#{dir.path}/mix.exs")
|
|
56
|
+
rescue Dependabot::DependencyFileNotFound
|
|
57
|
+
# If the folder doesn't have a mix.exs it *might* be because it's
|
|
58
|
+
# not an app. Ignore the fact we couldn't fetch one and proceed with
|
|
59
|
+
# updating (it will blow up later if there are problems)
|
|
60
|
+
nil
|
|
61
|
+
end.compact
|
|
62
|
+
rescue Octokit::NotFound, Gitlab::Error::NotFound
|
|
63
|
+
# If the path specified in apps_path doesn't exist then it's not being
|
|
64
|
+
# used. We can just return an empty array of subapp files.
|
|
65
|
+
[]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def evaled_files
|
|
69
|
+
mixfile.content.scan(EVAL_FILE).map do |eval_file_args|
|
|
70
|
+
path = Pathname.new(File.join(*eval_file_args.reverse)).
|
|
71
|
+
cleanpath.to_path
|
|
72
|
+
fetch_file_from_host(path).tap { |f| f.support_file = true }
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
Dependabot::FileFetchers.register("hex", Dependabot::Hex::FileFetcher)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dependabot/dependency"
|
|
4
|
+
require "dependabot/file_parsers"
|
|
5
|
+
require "dependabot/file_parsers/base"
|
|
6
|
+
require "dependabot/hex/native_helpers"
|
|
7
|
+
require "dependabot/shared_helpers"
|
|
8
|
+
require "dependabot/errors"
|
|
9
|
+
|
|
10
|
+
# For docs, see https://hexdocs.pm/mix/Mix.Tasks.Deps.html
|
|
11
|
+
module Dependabot
|
|
12
|
+
module Hex
|
|
13
|
+
class FileParser < Dependabot::FileParsers::Base
|
|
14
|
+
require "dependabot/file_parsers/base/dependency_set"
|
|
15
|
+
|
|
16
|
+
def parse
|
|
17
|
+
dependency_set = DependencySet.new
|
|
18
|
+
|
|
19
|
+
dependency_details.each do |dep|
|
|
20
|
+
git_dependency = dep["source"]&.fetch("type") == "git"
|
|
21
|
+
|
|
22
|
+
dependency_set <<
|
|
23
|
+
Dependency.new(
|
|
24
|
+
name: dep["name"],
|
|
25
|
+
version: git_dependency ? dep["checksum"] : dep["version"],
|
|
26
|
+
requirements: [{
|
|
27
|
+
requirement: dep["requirement"],
|
|
28
|
+
groups: dep["groups"],
|
|
29
|
+
source: dep["source"] && symbolize_keys(dep["source"]),
|
|
30
|
+
file: dep["from"]
|
|
31
|
+
}],
|
|
32
|
+
package_manager: "hex"
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
dependency_set.dependencies.sort_by(&:name)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def dependency_details
|
|
42
|
+
SharedHelpers.in_a_temporary_directory do
|
|
43
|
+
write_sanitized_mixfiles
|
|
44
|
+
write_supporting_files
|
|
45
|
+
File.write("mix.lock", lockfile.content) if lockfile
|
|
46
|
+
FileUtils.cp(elixir_helper_parse_deps_path, "parse_deps.exs")
|
|
47
|
+
|
|
48
|
+
SharedHelpers.run_helper_subprocess(
|
|
49
|
+
env: mix_env,
|
|
50
|
+
command: "mix run #{elixir_helper_path}",
|
|
51
|
+
function: "parse",
|
|
52
|
+
args: [Dir.pwd],
|
|
53
|
+
popen_opts: { err: %i(child out) }
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
rescue Dependabot::SharedHelpers::HelperSubprocessFailed => error
|
|
57
|
+
result_json =
|
|
58
|
+
error.message.lines.
|
|
59
|
+
drop_while { |l| !l.start_with?('{"result":') }.
|
|
60
|
+
join
|
|
61
|
+
|
|
62
|
+
raise DependencyFileNotEvaluatable, error.message if result_json.empty?
|
|
63
|
+
|
|
64
|
+
JSON.parse(result_json).fetch("result")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def write_sanitized_mixfiles
|
|
68
|
+
mixfiles.each do |file|
|
|
69
|
+
path = file.name
|
|
70
|
+
FileUtils.mkdir_p(Pathname.new(path).dirname)
|
|
71
|
+
File.write(path, sanitize_mixfile(file.content))
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def write_supporting_files
|
|
76
|
+
dependency_files.select(&:support_file).each do |file|
|
|
77
|
+
path = file.name
|
|
78
|
+
FileUtils.mkdir_p(Pathname.new(path).dirname)
|
|
79
|
+
File.write(path, file.content)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def sanitize_mixfile(content)
|
|
84
|
+
content.
|
|
85
|
+
gsub(/File\.read!\(.*?\)/, '"0.0.1"').
|
|
86
|
+
gsub(/File\.read\(.*?\)/, '{:ok, "0.0.1"}')
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def mix_env
|
|
90
|
+
{
|
|
91
|
+
"MIX_EXS" => File.join(NativeHelpers.hex_helpers_dir, "mix.exs"),
|
|
92
|
+
"MIX_LOCK" => File.join(NativeHelpers.hex_helpers_dir, "mix.lock"),
|
|
93
|
+
"MIX_DEPS" => File.join(NativeHelpers.hex_helpers_dir, "deps"),
|
|
94
|
+
"MIX_QUIET" => "1"
|
|
95
|
+
}
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def elixir_helper_path
|
|
99
|
+
File.join(NativeHelpers.hex_helpers_dir, "lib/run.exs")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def elixir_helper_parse_deps_path
|
|
103
|
+
File.join(NativeHelpers.hex_helpers_dir, "lib/parse_deps.exs")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def check_required_files
|
|
107
|
+
raise "No mixfile!" if mixfiles.none?
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def symbolize_keys(hash)
|
|
111
|
+
Hash[hash.keys.map { |k| [k.to_sym, hash[k]] }]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def mixfiles
|
|
115
|
+
dependency_files.select { |f| f.name.end_with?("mix.exs") }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def lockfile
|
|
119
|
+
@lockfile ||= get_original_file("mix.lock")
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
Dependabot::FileParsers.register("hex", Dependabot::Hex::FileParser)
|