Skip to content

Commit 6ea7d3c

Browse files
committed
Fetch Hex with wget or curl
This way we can use https and do peer verification without bundling certificates with elixir.
1 parent 1dd034d commit 6ea7d3c

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

lib/mix/lib/mix/tasks/archive.install.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ defmodule Mix.Tasks.Archive.Install do
3030
"""
3131
@spec run(OptionParser.argv) :: boolean
3232
def run(argv) do
33-
{opts, argv, _} = OptionParser.parse(argv, switches: [force: :boolean])
33+
{opts, argv, _} = OptionParser.parse(argv, switches: [force: :boolean, shell: :boolean])
3434

3535
if src = List.first(argv) do
3636
%URI{path: path} = URI.parse(src)
@@ -58,7 +58,7 @@ defmodule Mix.Tasks.Archive.Install do
5858
dest = Mix.Local.archives_path()
5959
File.mkdir_p!(dest)
6060
archive = Path.join(dest, basename(src))
61-
create_file archive, Mix.Utils.read_path!(src)
61+
create_file archive, Mix.Utils.read_path!(src, opts)
6262
true = Code.append_path(Mix.Archive.ebin(archive))
6363
else
6464
false

lib/mix/lib/mix/tasks/local.hex.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ defmodule Mix.Tasks.Local.Hex do
1818
"""
1919
@spec run(OptionParser.argv) :: boolean
2020
def run(args) do
21-
Mix.Tasks.Archive.Install.run [@hex_url|args]
21+
Mix.Tasks.Archive.Install.run [@hex_url, "--shell" | args]
2222
end
2323

2424
@doc false

lib/mix/lib/mix/utils.ex

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -359,22 +359,32 @@ defmodule Mix.Utils do
359359
Used by tasks like `archive.install` and `local.rebar` that support
360360
installation either from a URL or a local file.
361361
362-
Raises if the given path is not a url, nor a file or if the
363-
file or url are invalid.
362+
Raises if the given path is not a URL, nor a file or if the
363+
file or URL are invalid.
364+
365+
## Options
366+
367+
* `:shell` - Forces the use of `wget` or `curl` to fetch the file if the
368+
given path is a URL.
364369
"""
365-
def read_path!(path) do
370+
def read_path!(path, opts \\ []) do
366371
cond do
367-
url?(path) -> read_url(path)
368-
file?(path) -> read_file(path)
369-
:else -> Mix.raise "Expected #{path} to be a url or a local file path"
372+
url?(path) && opts[:shell] ->
373+
read_shell(path)
374+
url?(path) ->
375+
read_httpc(path)
376+
file?(path) ->
377+
read_file(path)
378+
true ->
379+
Mix.raise "Expected #{path} to be a url or a local file path"
370380
end
371381
end
372382

373383
defp read_file(path) do
374384
File.read!(path)
375385
end
376386

377-
defp read_url(path) do
387+
defp read_httpc(path) do
378388
{:ok, _} = Application.ensure_all_started(:ssl)
379389
{:ok, _} = Application.ensure_all_started(:inets)
380390

@@ -420,6 +430,33 @@ defmodule Mix.Utils do
420430
end
421431
end
422432

433+
defp read_shell(path) do
434+
filename = URI.parse(path).path |> Path.basename
435+
out_path = Path.join(System.tmp_dir!, filename)
436+
File.rm(out_path)
437+
438+
cond do
439+
System.find_executable("wget") ->
440+
Mix.shell.cmd(~s(wget -O "#{out_path}" "#{path}"))
441+
System.find_executable("curl") ->
442+
Mix.shell.cmd(~s(curl -L -o "#{out_path}" "#{path}"))
443+
windows? && System.find_executable("powershell") ->
444+
command = ~s[$client = new-object System.Net.WebClient; ] <>
445+
~s[$client.DownloadFile(\\"#{path}\\", \\"#{out_path}\\")]
446+
Mix.shell.cmd(~s[powershell -Command "& {#{command}}"])
447+
true ->
448+
Mix.raise "wget or curl not installed, download manually: #{path}"
449+
end
450+
451+
data = File.read!(out_path)
452+
File.rm!(out_path)
453+
data
454+
end
455+
456+
def windows? do
457+
match?({:win32, _}, :os.type)
458+
end
459+
423460
defp file?(path) do
424461
File.regular?(path)
425462
end

0 commit comments

Comments
 (0)