Skip to content

Commit

Permalink
Merge pull request #56 from JamesS237/more_api_organisation
Browse files Browse the repository at this point in the history
Further API movement/organisation
  • Loading branch information
ericmj committed Aug 25, 2014
2 parents def093c + c075365 commit 57ff66f
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 79 deletions.
57 changes: 3 additions & 54 deletions lib/hex/api.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
defmodule Hex.API do
alias Hex.API.Util

def request(method, url, headers, body \\ nil) when body == nil or is_map(body) do
default_headers = %{
'accept' => 'application/vnd.hex.beta+elixir',
Expand Down Expand Up @@ -62,7 +64,7 @@ defmodule Hex.API do
headers = Enum.into(headers, %{})
content_encoding = :binary.list_to_bin(headers['content-encoding'] || '')
content_type = :binary.list_to_bin(headers['content-type'] || '')
handle_hex_message(headers['x-hex-message'])
Util.handle_hex_message(headers['x-hex-message'])

if String.contains?(content_encoding, "gzip") do
body = :zlib.gunzip(body)
Expand All @@ -75,18 +77,6 @@ defmodule Hex.API do
{code, body}
end

@doc false
def handle_hex_message(nil), do: :ok

def handle_hex_message(header) do
{message, level} = :binary.list_to_bin(header) |> parse_hex_message
case level do
"warn" -> Mix.shell.info("API warning: " <> message)
"fatal" -> Mix.shell.error("API error: " <> message)
_ -> :ok
end
end

def user_agent do
'Hex/#{Hex.version} (Elixir/#{System.version})'
end
Expand All @@ -111,45 +101,4 @@ defmodule Hex.API do
base64 = :base64.encode_to_string(info[:user] <> ":" <> info[:pass])
%{'authorization' => 'Basic ' ++ base64}
end

@space [?\s, ?\t]

defp parse_hex_message(message) do
{message, rest} = skip_ws(message) |> quoted
level = skip_ws(rest) |> opt_level
{message, level}
end

defp skip_ws(<< char, rest :: binary >>) when char in @space,
do: skip_ws(rest)
defp skip_ws(rest),
do: rest

defp skip_trail_ws(input, str \\ "", ws \\ "")

defp skip_trail_ws(<< char, rest :: binary >>, str, ws) when char in @space,
do: skip_trail_ws(rest, str, << ws :: binary, char >>)
defp skip_trail_ws(<< char, rest :: binary >>, str, ws),
do: skip_trail_ws(rest, << str :: binary, ws :: binary, char >>, "")
defp skip_trail_ws("", str, _ws),
do: str

defp quoted("\"" <> rest),
do: do_quoted(rest, "")

defp do_quoted("\"" <> rest, acc),
do: {acc, rest}
defp do_quoted(<< char, rest :: binary >>, acc),
do: do_quoted(rest, << acc :: binary, char >>)

defp opt_level(";" <> rest),
do: do_level(rest)
defp opt_level(_),
do: nil

defp do_level(rest) do
"level" <> rest = skip_ws(rest)
"=" <> rest = skip_ws(rest)
skip_ws(rest) |> skip_trail_ws
end
end
14 changes: 0 additions & 14 deletions lib/hex/api/package.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,4 @@ defmodule Hex.API.Package do
def new(name, meta, auth) do
API.request(:put, API.api_url("packages/#{name}"), API.auth(auth), %{meta: meta})
end

def add_owner(package, owner, auth) do
owner = URI.encode_www_form(owner)
API.request(:put, API.api_url("packages/#{package}/owners/#{owner}"), API.auth(auth))
end

def delete_owner(package, owner, auth) do
owner = URI.encode_www_form(owner)
API.request(:delete, API.api_url("packages/#{package}/owners/#{owner}"), API.auth(auth))
end

def get_owners(package, auth) do
API.request(:get, API.api_url("packages/#{package}/owners"), API.auth(auth))
end
end
17 changes: 17 additions & 0 deletions lib/hex/api/package_owner.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule Hex.API.Package.Owner do
alias Hex.API

def add(package, owner, auth) do
owner = URI.encode_www_form(owner)
API.request(:put, API.api_url("packages/#{package}/owners/#{owner}"), API.auth(auth))
end

def delete(package, owner, auth) do
owner = URI.encode_www_form(owner)
API.request(:delete, API.api_url("packages/#{package}/owners/#{owner}"), API.auth(auth))
end

def get(package, auth) do
API.request(:get, API.api_url("packages/#{package}/owners"), API.auth(auth))
end
end
54 changes: 54 additions & 0 deletions lib/hex/api/util.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
defmodule Hex.API.Util do
@doc false
def handle_hex_message(nil), do: :ok

def handle_hex_message(header) do
{message, level} = :binary.list_to_bin(header) |> parse_hex_message
case level do
"warn" -> Mix.shell.info("API warning: " <> message)
"fatal" -> Mix.shell.error("API error: " <> message)
_ -> :ok
end
end

@space [?\s, ?\t]

def parse_hex_message(message) do
{message, rest} = skip_ws(message) |> quoted
level = skip_ws(rest) |> opt_level
{message, level}
end

def skip_ws(<< char, rest :: binary >>) when char in @space,
do: skip_ws(rest)
def skip_ws(rest),
do: rest

def skip_trail_ws(input, str \\ "", ws \\ "")

def skip_trail_ws(<< char, rest :: binary >>, str, ws) when char in @space,
do: skip_trail_ws(rest, str, << ws :: binary, char >>)
def skip_trail_ws(<< char, rest :: binary >>, str, ws),
do: skip_trail_ws(rest, << str :: binary, ws :: binary, char >>, "")
def skip_trail_ws("", str, _ws),
do: str

def quoted("\"" <> rest),
do: do_quoted(rest, "")

def do_quoted("\"" <> rest, acc),
do: {acc, rest}
def do_quoted(<< char, rest :: binary >>, acc),
do: do_quoted(rest, << acc :: binary, char >>)

def opt_level(";" <> rest),
do: do_level(rest)
def opt_level(_),
do: nil

def do_level(rest) do
"level" <> rest = skip_ws(rest)
"=" <> rest = skip_ws(rest)
skip_ws(rest) |> skip_trail_ws
end
end
6 changes: 3 additions & 3 deletions lib/mix/tasks/hex/owner.ex
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ defmodule Mix.Tasks.Hex.Owner do

defp add_owner(package, owner, opts) do
Mix.shell.info("Adding owner #{owner} to #{package}")
case Hex.API.Package.add_owner(package, owner, opts) do
case Hex.API.Package.Owner.add(package, owner, opts) do
{204, _body} ->
:ok
{code, body} ->
Expand All @@ -63,7 +63,7 @@ defmodule Mix.Tasks.Hex.Owner do

defp remove_owner(package, owner, opts) do
Mix.shell.info("Removing owner #{owner} from #{package}")
case Hex.API.Package.delete_owner(package, owner, opts) do
case Hex.API.Package.Owner.delete(package, owner, opts) do
{204, _body} ->
:ok
{code, body} ->
Expand All @@ -73,7 +73,7 @@ defmodule Mix.Tasks.Hex.Owner do
end

defp list_owners(package, opts) do
case Hex.API.Package.get_owners(package, opts) do
case Hex.API.Package.Owner.get(package, opts) do
{200, body} ->
Enum.each(body, &Mix.shell.info(&1["email"]))
{code, body} ->
Expand Down
16 changes: 8 additions & 8 deletions test/hex/api_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -70,26 +70,26 @@ defmodule Hex.APITest do
Hex.API.Package.new("orange", %{}, auth)
Hex.API.User.new("orange_user", "[email protected]", "hunter42")

assert {200, [%{"username" => "user"}]} = Hex.API.Package.get_owners("orange", auth)
assert {200, [%{"username" => "user"}]} = Hex.API.Package.Owner.get("orange", auth)

assert {204, _} = Hex.API.Package.add_owner("orange", "[email protected]", auth)
assert {204, _} = Hex.API.Package.Owner.add("orange", "[email protected]", auth)

assert {200, [%{"username" => "user"}, %{"username" => "orange_user"}]} =
Hex.API.Package.get_owners("orange", auth)
Hex.API.Package.Owner.get("orange", auth)

assert {204, _} = Hex.API.Package.delete_owner("orange", "[email protected]", auth)
assert {204, _} = Hex.API.Package.Owner.delete("orange", "[email protected]", auth)

assert {200, [%{"username" => "user"}]} = Hex.API.Package.get_owners("orange", auth)
assert {200, [%{"username" => "user"}]} = Hex.API.Package.Owner.get("orange", auth)
end

test "x-hex-message" do
Hex.API.handle_hex_message('"oops, you done goofed"')
Hex.API.Util.handle_hex_message('"oops, you done goofed"')
refute_received {:mix_shell, _, _}

Hex.API.handle_hex_message(' "oops, you done goofed" ; level = warn')
Hex.API.Util.handle_hex_message(' "oops, you done goofed" ; level = warn')
assert_received {:mix_shell, :info, ["API warning: oops, you done goofed"]}

Hex.API.handle_hex_message('"oops, you done goofed";level=fatal ')
Hex.API.Util.handle_hex_message('"oops, you done goofed";level=fatal ')
assert_received {:mix_shell, :error, ["API error: oops, you done goofed"]}
end
end

0 comments on commit 57ff66f

Please sign in to comment.