Current section

Files

Jump to
exgpg lib exgpg.ex
Raw

lib/exgpg.ex

defmodule Exgpg do
@global_args [no_use_agent: true, batch: true, no_default_keyring: true]
@without_input [
list_key: [{:with_colons, true} | @global_args],
version: []
]
@with_input [
gen_key: @global_args,
encrypt: @global_args,
decrypt: @global_args,
symmetric: @global_args
]
defmodule AbnormalExit do
defexception [:output, :status]
def message(%{status: status, output: _}) do
"exited with non-zero status (#{status})"
end
end
Enum.each(@without_input, fn {command, args} ->
def unquote(command)(user_args \\ []) do
args = [{unquote(command), true} | unquote(args)]
{nil, args, user_args}
|> run(unquote(command))
|> adapt_out(unquote(command))
end
end)
Enum.each(@with_input, fn {command, args} ->
def unquote(command)(input \\ nil, user_args \\ []) do
args = [{unquote(command), true} | unquote(args)]
{input, args, user_args}
|> adapt_in(unquote(command))
|> run(unquote(command))
|> adapt_out(unquote(command))
end
end)
defp run({nil, args, user_args}, _) do
spawn_opts = [out: :stream]
gpg(args, user_args, spawn_opts)
end
defp run({input, args, user_args}, _) do
spawn_opts = [in: input, out: :stream]
gpg(args, user_args, spawn_opts)
end
defp gpg(args, user_args, spawn_opts) do
argv = args
|> Enum.concat(user_args)
|> OptionParser.to_argv
IO.puts "Running gpg #{Enum.join(argv, " ")}"
Porcelain.spawn("gpg", argv, spawn_opts)
end
def adapt_in({_input, _args, user_args}, :gen_key) do
input = user_args
|> Enum.filter(fn {key, _} -> key != :gen_key end)
|> Enum.map(fn {key, val} -> {Atom.to_string(key), val} end)
|> Enum.map(fn {key, val} -> to_genkey(key, val) end)
|> Enum.join("\n")
IO.puts input
{input, [{:gen_key, true} | @global_args], []}
end
def adapt_in({input, args, user_args}, _), do: {input, args, user_args}
def adapt_out(result, :list_key) do
result.out
|> Enum.into("")
|> String.split("\n")
|> Enum.drop(1)
|> Enum.map(fn s ->
s
|> String.split(":")
|> Enum.filter(&(&1 != ""))
end)
|> Enum.filter(&(&1 != []))
|> Enum.chunk(2)
|> Enum.map(&(List.to_tuple &1))
end
def adapt_out(proc, _) do
Porcelain.Process.send_input(proc, "")
proc.out
end
defp to_genkey("ctrl_" <> rest, ""), do: "%" <> rest
defp to_genkey("ctrl_" <> rest, val) do
("%" <> rest) <> (" " <> val)
end
defp to_genkey(key, val) do
(key
|> String.split("_")
|> Enum.map(&String.capitalize &1)
|> Enum.join("-")) <> (": " <> "#{val}")
end
end