-
Notifications
You must be signed in to change notification settings - Fork 3.3k
/
escript.ex
57 lines (45 loc) · 1.43 KB
/
escript.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
defmodule Mix.Tasks.Escript do
use Mix.Task
@shortdoc "Lists installed escripts"
@moduledoc ~S"""
Lists all installed escripts.
Escripts are installed at `~/.mix/escripts`. Add that path to your `$PATH` environment variable
to be able to run installed escripts from any directory.
"""
import Bitwise, only: [|||: 2, &&&: 2]
@impl true
def run(_) do
escripts_path = Mix.path_for(:escripts)
escripts_path
|> list_dir()
|> Enum.filter(fn filename -> executable?(Path.join(escripts_path, filename)) end)
|> print()
end
defp list_dir(path) do
case File.ls(path) do
{:ok, list} -> list
_ -> []
end
end
defp executable?(path) do
owner_exec_bit = 0o00100
group_exec_bit = 0o00010
other_exec_bit = 0o00001
stat = File.stat!(path)
case :os.type() do
{:win32, _} ->
# on win32, the script itself is not executable, but the bat is
File.exists?(path <> ".bat") and stat.type == :regular
_ ->
executable_bit = stat.mode &&& (owner_exec_bit ||| group_exec_bit ||| other_exec_bit)
executable_bit != 0 and stat.type == :regular and Path.extname(path) != ".bat"
end
end
defp print([]) do
Mix.shell().info("No escripts currently installed.")
end
defp print(items) do
Enum.each(items, fn item -> Mix.shell().info(["* ", item]) end)
Mix.shell().info("Escripts installed at: #{Mix.path_for(:escripts)}")
end
end