Skip to content

Commit c45d0f4

Browse files
author
José Valim
committed
No longer support .beam files on mix local
1 parent 406f0dc commit c45d0f4

File tree

9 files changed

+68
-139
lines changed

9 files changed

+68
-139
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
* backwards incompatible changes
2424
* [File] `rm_rf` and `cp_r` now returns a tuple with three elements on failures
2525
* [Kernel] The quoted representation for `->` clauses changed from a tuple with two elements to a tuple with three elements to support metadata
26+
* [Mix] No longer support beam files on `mix local`
2627

2728
# v0.9.2 (2013-06-13)
2829

lib/mix/lib/mix/cli.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ defmodule Mix.CLI do
5252
end
5353

5454
defp proceed(args) do
55-
Mix.Local.append_tasks
55+
Mix.Local.append_archives
5656
Mix.Local.append_paths
5757

5858
args = load_mixfile(args)

lib/mix/lib/mix/local.ex

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,36 @@
11
defmodule Mix.Local do
22
@moduledoc """
3-
Module responsible to manage local .mix installation.
3+
Module responsible to manage local mix archives and paths.
44
"""
55

66
@doc """
7-
The path for local tasks and archives.
7+
The path for local archives.
88
"""
9-
def tasks_path do
10-
Path.join Mix.Utils.mix_home, "tasks"
9+
def archives_path do
10+
Path.join Mix.Utils.mix_home, "archives"
1111
end
1212

1313
@doc """
14-
Append local tasks and archives paths into Erlang code path.
14+
Append archives paths into Erlang code path.
1515
"""
16-
def append_tasks do
17-
Enum.each(all_tasks_paths, Code.append_path(&1))
16+
def append_archives do
17+
Enum.each(archives_ebin, Code.append_path(&1))
1818
end
1919

2020
@doc """
2121
Append mix paths into Erlang code path.
2222
"""
2323
def append_paths do
24-
Enum.each(Mix.Utils.mix_path, Code.append_path(&1))
24+
Enum.each(Mix.Utils.mix_paths, Code.append_path(&1))
2525
end
2626

2727
@doc """
28-
Returns all tasks modules in ~/.mix/tasks and archives.
28+
Returns all tasks in local archives.
2929
"""
30-
def all_tasks, do: Mix.Task.load_paths(all_tasks_paths)
30+
def all_tasks, do: Mix.Task.load_tasks(archives_ebin)
3131

32-
defp all_tasks_paths do
33-
[tasks_path | archives_paths]
34-
end
35-
36-
defp archives_paths do
37-
Path.join(tasks_path, "*.ez") |> Path.wildcard |> Enum.map(archive_ebin(&1))
32+
defp archives_ebin do
33+
Path.join(archives_path, "*.ez") |> Path.wildcard |> Enum.map(archive_ebin(&1))
3834
end
3935

4036
defp archive_ebin(archive_file) do

lib/mix/lib/mix/task.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ defmodule Mix.Task do
2525
@doc """
2626
Loads all tasks in all code paths.
2727
"""
28-
def load_all, do: load_paths(:code.get_path)
28+
def load_all, do: load_tasks(:code.get_path)
2929

3030
@doc """
3131
Loads all tasks in given paths.
3232
"""
33-
def load_paths(paths) do
33+
def load_tasks(paths) do
3434
Enum.reduce(paths, [], fn(path, matches) ->
3535
{ :ok, files } = :erl_prim_loader.list_dir(path |> :unicode.characters_to_list)
3636
Enum.reduce(files, matches, match_tasks(&1, &2))

lib/mix/lib/mix/tasks/local.install.ex

Lines changed: 12 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,26 @@ defmodule Mix.Tasks.Local.Install do
66
@shortdoc "Install a task or an archive locally"
77

88
@moduledoc """
9-
Install a task or an archive locally.
9+
Install an archive locally.
1010
1111
If no argument is supplied but there is an archive in the root
1212
(created with mix archive), then the archive will be installed
1313
locally. For example:
1414
1515
mix do archive, local.install
1616
17-
The task can also be a single local beam file or a beam
18-
file located at some URL.
17+
The task can also be an archive located at some URL:
1918
20-
mix local.install http://example.com/some_task.beam
19+
mix local.install http://example.com/foo.ez
2120
22-
After installed, the task can be invoked locally:
21+
After installed, the tasks in the archive are available locally:
2322
2423
mix some_task
2524
2625
## Command line options
2726
2827
* `--force` forces installation without a shell prompt. Primarily
29-
intended for automation in build systems like Make.
28+
intended for automation in build systems like make.
3029
3130
"""
3231

@@ -41,50 +40,16 @@ defmodule Mix.Tasks.Local.Install do
4140
end
4241

4342
case Path.extname(path) do
44-
".ez" -> install_archive(path, opts)
45-
".beam" -> install_beam(path, opts)
46-
_ ->
47-
raise Mix.Error, message: "mix local.install doesn't know how to install #{path}"
43+
".ez" -> install_archive(path, opts)
44+
_ -> raise Mix.Error, message: "mix local.install doesn't know how to install #{path}"
4845
end
4946
end
5047

51-
defp install_beam(path, opts) do
52-
beam = Mix.Utils.read_path(path)
53-
{ :module, module } = get_module(path, beam)
54-
55-
validate_module_name!(path, module)
56-
task_name = Mix.Task.task_name(module)
57-
58-
if opts[:force] || Mix.shell.yes?("Are you sure you want to install task #{inspect task_name}?") do
59-
tasks = Mix.Local.tasks_path
60-
File.mkdir_p! tasks
61-
create_file Path.join(tasks, "#{module}.beam"), beam
62-
end
63-
end
64-
65-
defp install_archive(name, opts) do
66-
if opts[:force] || Mix.shell.yes?("Are you sure you want to install archive #{name}?") do
67-
tasks = Mix.Local.tasks_path
68-
File.mkdir_p! tasks
69-
File.copy(name, Path.join(tasks, name))
70-
end
71-
end
72-
73-
defp get_module(path, beam) do
74-
case :beam_lib.info(beam) do
75-
list when is_list(list) ->
76-
List.keyfind list, :module, 0
77-
_ ->
78-
raise Mix.Error, message: "could not parse beam file at #{path}"
79-
end
80-
end
81-
82-
defp validate_module_name!(path, module) do
83-
case atom_to_binary(module) do
84-
"Elixir.Mix.Tasks." <> _ ->
85-
:ok
86-
other ->
87-
raise Mix.Error, message: "expected a Mix.Tasks module at #{path}, got #{other}"
48+
defp install_archive(src, opts) do
49+
if opts[:force] || Mix.shell.yes?("Are you sure you want to install archive #{src}?") do
50+
dest = Mix.Local.archives_path
51+
File.mkdir_p! dest
52+
create_file Path.join(dest, Path.basename(src)), Mix.Utils.read_path(src)
8853
end
8954
end
9055
end

lib/mix/lib/mix/tasks/local.uninstall.ex

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@ defmodule Mix.Tasks.Local.Uninstall do
1717

1818
defp do_uninstall(task) do
1919
case Path.extname(task) do
20-
".ez" -> File.rm! Path.join(Mix.Local.tasks_path, task)
20+
".ez" -> File.rm! Path.join(Mix.Local.archives_path, task)
2121
_ ->
2222
task_module = Mix.Task.get(task)
23-
if archive = in_archive('#{task_module}.beam') do
24-
raise Mix.Error, message: "The task #{task} is part of archive #{archive}. " <>
25-
"To uninstall this task, please run: `mix local.uninstall #{archive}`"
23+
archive = in_archive('#{task_module}.beam')
24+
25+
if archive && Mix.shell.yes?("The task #{task} is part of archive #{archive}. " <>
26+
"Do you want to remove this archive?") do
27+
do_uninstall(archive)
2628
else
27-
File.rm! Path.join(Mix.Local.tasks_path, "#{task_module}.beam")
29+
raise Mix.Error, message: "cannot uninstall task #{task}"
2830
end
2931
end
3032
end

lib/mix/lib/mix/utils.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ defmodule Mix.Utils do
2828
those paths should be separated by `;`, if on unix systems,
2929
use `:`.
3030
"""
31-
def mix_path do
31+
def mix_paths do
3232
if path = System.get_env("MIX_PATH") do
3333
String.split(path, path_separator)
3434
else

lib/mix/test/mix/tasks/local_archive_test.exs

Lines changed: 0 additions & 44 deletions
This file was deleted.

lib/mix/test/mix/tasks/local_test.exs

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,45 @@ Code.require_file "../../test_helper.exs", __DIR__
33
defmodule Mix.Tasks.LocalTest do
44
use MixTest.Case
55

6-
test "manage local tasks" do
6+
test "archive" do
77
File.rm_rf! tmp_path("userhome")
88
System.put_env "MIX_HOME", tmp_path("userhome/.mix")
99

10-
# Install it!
11-
self <- { :mix_shell_input, :yes?, true }
12-
Mix.Tasks.Local.Install.run [fixture_path("beams/Elixir.Mix.Tasks.Local.Sample.beam")]
13-
assert File.regular? tmp_path("userhome/.mix/tasks/Elixir.Mix.Tasks.Local.Sample.beam")
14-
15-
# List it!
16-
Mix.Local.append_tasks
17-
Mix.Tasks.Local.run []
18-
assert_received { :mix_shell, :info, ["mix local.sample # A local install sample"] }
19-
20-
# Run it!
21-
Mix.Task.run "local.sample"
22-
assert_received { :mix_shell, :info, ["sample"] }
23-
24-
# Remove it!
25-
Mix.Tasks.Local.Uninstall.run ["local.sample"]
26-
refute File.regular? tmp_path("userhome/.mix/tasks/Elixir.Mix.Tasks.Local.Sample.beam")
10+
in_fixture "archive", fn() ->
11+
# Install it!
12+
Mix.Tasks.Archive.run ["--no_compile"]
13+
assert File.regular? "test archive.ez"
14+
15+
self <- { :mix_shell_input, :yes?, true }
16+
Mix.Tasks.Local.Install.run ["test archive.ez"]
17+
assert File.regular? tmp_path("userhome/.mix/archives/test archive.ez")
18+
19+
# List it!
20+
Mix.Local.append_archives
21+
Mix.Tasks.Local.run []
22+
assert_received { :mix_shell, :info, ["mix local.sample # A local install sample"] }
23+
24+
# Run it!
25+
Mix.Task.run "local.sample"
26+
assert_received { :mix_shell, :info, ["sample"] }
27+
28+
# Remove it!
29+
self <- { :mix_shell_input, :yes?, true }
30+
Mix.Tasks.Local.Uninstall.run ["local.sample"]
31+
refute File.regular? tmp_path("userhome/.mix/archives/test archive.ez")
32+
end
2733
end
2834

29-
test "manage mix paths" do
30-
File.rm_rf! tmp_path("userhome")
31-
System.put_env "MIX_PATH", tmp_path("userhome/.mix")
35+
test "MIX_PATH" do
36+
File.rm_rf! tmp_path("mixpath")
37+
System.put_env "MIX_PATH", tmp_path("mixpath/ebin")
38+
39+
File.mkdir_p! tmp_path("mixpath/ebin")
40+
Mix.Local.append_paths
3241

3342
# Install on MIX_PATH manually
34-
File.cp fixture_path("beams/Elixir.Mix.Tasks.Local.Sample.beam"),
35-
tmp_path("userhome/.mix/tasks/Elixir.Mix.Tasks.Local.Sample.beam")
43+
File.copy! fixture_path("beams/Elixir.Mix.Tasks.Local.Sample.beam"),
44+
tmp_path("mixpath/ebin/Elixir.Mix.Tasks.Local.Sample.beam")
3645

3746
# Run it
3847
Mix.Task.run "local.sample"

0 commit comments

Comments
 (0)