Skip to content

Commit

Permalink
v0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ericentin committed Apr 19, 2019
1 parent 1828403 commit 223c2c8
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 267 deletions.
3 changes: 3 additions & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
28 changes: 22 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
/.dialyxir
/_build
/cover
/deps
/doc
/docs
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where third-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore package tarball (built via "mix hex.build").
exexec-*.tar

23 changes: 5 additions & 18 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,14 @@
dist: xenial
sudo: false
language: elixir
elixir:
- 1.4.1
dist: trusty
- 1.8.1
otp_release:
- 18.3
sudo: false
- 21.3
env:
- MIX_ENV=test
- MIX_ENV=test ELIXIR_ERL_OPTIONS="+T 9"
before_script:
- mix compile --warnings-as-errors
- mix dialyzer --plt
script:
- mix coveralls.travis
- mix dialyzer --halt-exit-status
after_script:
- mix deps.get --only docs
- MIX_ENV=docs mix inch.report
cache:
directories:
- _build
- deps
addons:
apt:
packages:
- libcap-dev
- mix test
23 changes: 13 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/antipax/exexec.svg?branch=master)](https://travis-ci.org/antipax/exexec) [![Coverage Status](https://coveralls.io/repos/github/antipax/exexec/badge.svg?branch=master)](https://coveralls.io/github/antipax/exexec?branch=master) [![Inline docs](http://inch-ci.org/github/antipax/exexec.svg?branch=master)](http://inch-ci.org/github/antipax/exexec) [![Hex.pm package version](https://img.shields.io/hexpm/v/exexec.svg)](https://hex.pm/packages/exexec) [![Hex.pm package license](https://img.shields.io/hexpm/l/exexec.svg)](https://github.com/antipax/exexec/blob/master/LICENSE)
[![Build Status](https://travis-ci.org/ericentin/exexec.svg?branch=master)](https://travis-ci.org/ericentin/exexec) [![Hex.pm package version](https://img.shields.io/hexpm/v/exexec.svg)](https://hex.pm/packages/exexec) [![Hex.pm package license](https://img.shields.io/hexpm/l/exexec.svg)](https://github.com/ericentin/exexec/blob/master/LICENSE)

# Exexec

Expand All @@ -10,14 +10,17 @@ interface as well as some nice Elixir-y goodies on top.

## Installation

1. Add exexec to your list of dependencies in `mix.exs`:
The package can be installed
by adding `exexec` to your list of dependencies in `mix.exs`:

def deps do
[{:exexec, "~> 0.1"}]
end
```elixir
def deps do
[
{:exexec, "~> 0.2"}
]
end
```

2. Ensure exexec and erlexec are started before your application:

def application do
[applications: [:erlexec, :exexec]]
end
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/exexec](https://hexdocs.pm/exexec).
85 changes: 45 additions & 40 deletions lib/exexec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,68 +9,69 @@ defmodule Exexec do

import Exexec.ToErl

@type command :: String.t | [Path.t | [String.t]]
@type command :: String.t() | [Path.t() | [String.t()]]

@type os_pid :: non_neg_integer

@type gid :: non_neg_integer

@type output_file_option ::
{:append, boolean} |
{:mode, non_neg_integer}
{:append, boolean}
| {:mode, non_neg_integer}

@type output_device :: :stdout | :stderr

@type output_file_options :: [output_file_option]

@type output_device_option ::
boolean |
:null |
:close |
:print |
Path.t |
{Path.t, output_file_options} |
pid |
(output_device, os_pid, binary -> any)
boolean
| :null
| :close
| :print
| Path.t()
| {Path.t(), output_file_options}
| pid
| (output_device, os_pid, binary -> any)

@type command_option ::
{:monitor, boolean} |
{:sync, boolean} |
{:executable, Path.t} |
{:cd, Path.t} |
{:env, %{String.t => String.t}} |
{:kill_command, String.t} |
{:kill_timeout, non_neg_integer} |
{:kill_group, boolean} |
{:group, String.t} |
{:user, String.t} |
{:success_exit_code, exit_code} |
{:nice, -20..20} |
{:stdin, boolean | :null | :close | Path.t} |
{:stdout, :stderr | output_device_option} |
{:stderr, :stdout | output_device_option} |
{:pty, boolean}
{:monitor, boolean}
| {:sync, boolean}
| {:executable, Path.t()}
| {:cd, Path.t()}
| {:env, %{String.t() => String.t()}}
| {:kill_command, String.t()}
| {:kill_timeout, non_neg_integer}
| {:kill_group, boolean}
| {:group, String.t()}
| {:user, String.t()}
| {:success_exit_code, exit_code}
| {:nice, -20..20}
| {:stdin, boolean | :null | :close | Path.t()}
| {:stdout, :stderr | output_device_option}
| {:stderr, :stdout | output_device_option}
| {:pty, boolean}

@type command_options :: [command_option]

@type exec_option ::
{:debug, boolean | non_neg_integer} |
{:verbose, boolean} |
{:args, [String.t]} |
{:alarm, non_neg_integer} |
{:user, String.t} |
{:limit_users, [String.t]} |
{:port_path, Path.t} |
{:env, %{String.t => String.t}}
{:debug, boolean | non_neg_integer}
| {:root, boolean}
| {:verbose, boolean}
| {:args, [String.t()]}
| {:alarm, non_neg_integer}
| {:user, String.t()}
| {:limit_users, [String.t()]}
| {:port_path, Path.t()}
| {:env, %{String.t() => String.t()}}

@type exec_options :: [exec_option]

@type signal :: pos_integer

@type on_run ::
{:ok, pid, os_pid} |
{:ok, [{output_device, [binary]}]} |
{:error, any}
{:ok, pid, os_pid}
| {:ok, [{output_device, [binary]}]}
| {:error, any}

@type exit_code :: non_neg_integer

Expand Down Expand Up @@ -171,7 +172,9 @@ defmodule Exexec do
Start `Exexec` with `options`.
"""
@spec start(exec_options) :: {:ok, pid} | {:error, any}
defdelegate start(options), to: :exec
def start(options) do
:exec.start(exec_options_to_erl(options))
end

@doc """
Start `Exexec` and link to calling process.
Expand All @@ -183,7 +186,9 @@ defmodule Exexec do
Start `Exexec` with `options` and link to calling process.
"""
@spec start_link(exec_options) :: {:ok, pid} | {:error, any}
defdelegate start_link(options), to: :exec
def start_link(options) do
:exec.start_link(exec_options_to_erl(options))
end

@doc """
Interpret `exit_code`.
Expand Down
56 changes: 30 additions & 26 deletions lib/exexec/to_erl.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,36 @@ defmodule Exexec.ToErl do
@moduledoc false

def command_to_erl(command) when is_list(command) do
Enum.map(command, &to_char_list/1)
Enum.map(command, &to_charlist/1)
end

def command_to_erl(command) do
to_char_list(command)
to_charlist(command)
end

def command_options_to_erl(options) do
for {key, value} <- options,
option = command_option_to_erl(key, value),
do: option
do: option
end

@boolean_options [:monitor, :sync, :kill_group, :pty]
def command_option_to_erl(boolean_option, value)
when boolean_option in @boolean_options do
when boolean_option in @boolean_options do
if value, do: boolean_option
end

@string_options [:executable, :cd, :kill_command, :group, :user]
def command_option_to_erl(string_option, value)
when string_option in @string_options do
string_option =
if string_option == :kill_command, do: :kill, else: string_option
when string_option in @string_options do
string_option = if string_option == :kill_command, do: :kill, else: string_option

{string_option, to_char_list(value)}
{string_option, to_charlist(value)}
end

@integer_options [:kill_timeout, :success_exit_code, :nice]
def command_option_to_erl(integer_option, value)
when integer_option in @integer_options do
when integer_option in @integer_options do
{integer_option, value}
end

Expand All @@ -46,25 +45,29 @@ defmodule Exexec.ToErl do
if value do
case value do
true -> :stdin
string when is_binary(string) -> {:stdin, to_char_list(string)}
string when is_binary(string) -> {:stdin, to_charlist(string)}
other -> {:stdin, other}
end
end
end

@output_device_options [:stdout, :stderr]
def command_option_to_erl(output_device_option, value)
when output_device_option in @output_device_options do
other_option = List.delete(@output_device_options, output_device_option)
when output_device_option in @output_device_options do
[other_option] = List.delete(@output_device_options, output_device_option)

case value do
true -> output_device_option
false -> nil
true ->
output_device_option

false ->
nil

^other_option ->
{output_device_option, other_option}

{filename, output_file_options} ->
filename = to_char_list(filename)
filename = to_charlist(filename)
output_file_options = output_file_options_to_erl(output_file_options)
{output_device_option, filename, output_file_options}

Expand All @@ -76,7 +79,7 @@ defmodule Exexec.ToErl do
def output_device_option_to_erl(:null), do: :null
def output_device_option_to_erl(:close), do: :close
def output_device_option_to_erl(:print), do: :print
def output_device_option_to_erl(path) when is_binary(path), do: to_char_list(path)
def output_device_option_to_erl(path) when is_binary(path), do: to_charlist(path)
def output_device_option_to_erl(pid) when is_pid(pid), do: pid
def output_device_option_to_erl(fun) when is_function(fun, 3), do: fun

Expand All @@ -86,7 +89,7 @@ defmodule Exexec.ToErl do
do: option
end

def output_file_option_to_erl(:append, value), do: if value, do: :append
def output_file_option_to_erl(:append, value), do: if(value, do: :append)
def output_file_option_to_erl(:mode, value), do: {:mode, value}

def exec_options_to_erl(options) do
Expand All @@ -104,6 +107,10 @@ defmodule Exexec.ToErl do
end
end

def exec_option_to_erl(:root, value) do
{:root, value}
end

def exec_option_to_erl(:verbose, value) do
if value do
:verbose
Expand All @@ -114,24 +121,21 @@ defmodule Exexec.ToErl do
{:alarm, value}
end

@output_device_string_options [:user, :port_path]
def exec_option_to_erl(string_option, value)
when string_option in @output_device_string_options do
string_option =
if string_option == :port_path, do: :portexe, else: string_option
{string_option, to_char_list(value)}
when string_option in [:user, :port_path] do
string_option = if string_option == :port_path, do: :portexe, else: string_option
{string_option, to_charlist(value)}
end

@output_device_string_list_options [:args, :limit_users]
def exec_option_to_erl(string_list_option, value)
when string_list_option in @output_device_string_list_options do
{string_list_option, Enum.map(value, &to_char_list/1)}
when string_list_option in [:args, :limit_users] do
{string_list_option, Enum.map(value, &to_charlist/1)}
end

def exec_option_to_erl(:env, value) do
{:env, to_env(value)}
end

def to_env(value),
do: for {key, value} <- value, do: {to_char_list(key), to_char_list(value)}
do: for({key, value} <- value, do: {to_charlist(key), to_charlist(value)})
end
Loading

0 comments on commit 223c2c8

Please sign in to comment.