diff --git a/elixir/github_repo_cloner b/elixir/github_repo_cloner index 38245ab..d1a2154 100755 Binary files a/elixir/github_repo_cloner and b/elixir/github_repo_cloner differ diff --git a/elixir/lib/cli.ex b/elixir/lib/cli.ex index 034ade4..da60494 100644 --- a/elixir/lib/cli.ex +++ b/elixir/lib/cli.ex @@ -1,7 +1,9 @@ defmodule GithubRepoCloner.CLI do + alias GithubRepoCloner.Cloner + alias GithubRepoCloner.PageIterator + def main(args \\ []) do - args - |> List.first - |> GithubRepoCloner.Cloner.clone + username = List.first(args) + PageIterator.repeat(&Cloner.clone_page/1, %{username: username, page: 1}) end end diff --git a/elixir/lib/cloner.ex b/elixir/lib/cloner.ex index 9ab2f53..58c605f 100644 --- a/elixir/lib/cloner.ex +++ b/elixir/lib/cloner.ex @@ -2,19 +2,18 @@ defmodule GithubRepoCloner.Cloner do @http_client Application.compile_env(:github_repo_cloner, :http_client) @system Application.compile_env(:github_repo_cloner, :system) - def clone(nil), do: true + def clone_page(%{username: nil}), do: {:error, "No repositories found"} + def clone_page(%{page: nil}), do: {:error, "No repositories found"} - def clone(username) do + def clone_page(%{username: username, page: page}) do username - |> request_repo_info + |> request_repo_info(page) |> parse_response |> clone_repos(username) end - def clone, do: true - - defp request_repo_info(username) do - @http_client.get("https://api.github.com/users/#{username}/repos") + defp request_repo_info(username, page) do + @http_client.get("https://api.github.com/users/#{username}/repos?page=#{page}") end defp parse_response({:ok, %Tesla.Env{status: 200, body: body}}) do @@ -30,7 +29,11 @@ defmodule GithubRepoCloner.Cloner do |> run_command end + defp run_command("") do + {:error, "No repositories found"} + end + defp run_command(command) do - @system.cmd("sh", ["-c", command]) + {:ok, @system.cmd("sh", ["-c", command])} end end diff --git a/elixir/lib/page_iterator.ex b/elixir/lib/page_iterator.ex new file mode 100644 index 0000000..47bdaca --- /dev/null +++ b/elixir/lib/page_iterator.ex @@ -0,0 +1,12 @@ +defmodule GithubRepoCloner.PageIterator do + def repeat(function, arguments = %{page: page}) do + {status, _} = function.(%{arguments | page: page}) + repeat(function, arguments, status) + end + + def repeat(function, arguments = %{page: page}, :ok) do + repeat(function, %{arguments | page: page + 1}) + end + + def repeat(_function, %{page: page}, :error), do: {:ok, page} +end diff --git a/elixir/test/cloner_test.exs b/elixir/test/cloner_test.exs index 34fa0b6..8d98bab 100644 --- a/elixir/test/cloner_test.exs +++ b/elixir/test/cloner_test.exs @@ -3,8 +3,9 @@ defmodule GithubRepoCloner.ClonerTest do import Mox alias GithubRepoCloner.Cloner - test "clone\1: valid username with repos" do + test "clone_page\1: valid username with repos" do username = "murjax" + page = "2" clone_url1 = "https://github.com/murjax/spring_engine.git" clone_url2 = "https://github.com/murjax/burger_bot.git" name1 = "spring_engine" @@ -24,26 +25,26 @@ defmodule GithubRepoCloner.ClonerTest do {:ok, %Tesla.Env{status: 200, body: serialized_repo_info}} end) - result = Cloner.clone(username) + {:ok, result} = Cloner.clone_page(%{username: username, page: page}) assert ^result = expected_result end - test "clone\1: valid username without repos" do + test "clone_page\1: valid username without repos" do username = "murjax" - expected_result = {:ok, "Command executed: "} + page = "2" expect( GithubRepoCloner.Http.Mock, :get, fn _url -> {:ok, %Tesla.Env{status: 200, body: "[]"}} end) - result = Cloner.clone(username) - assert ^result = expected_result + {:error, result} = Cloner.clone_page(%{username: username, page: page}) + assert ^result = "No repositories found" end - test "clone\1: username not found" do + test "clone_page\1: username not found" do username = "foo" - expected_result = {:ok, "Command executed: "} + page = "2" response_body = %{"message" => "Not Found"} {_, serialized_response_body} = Poison.encode(response_body) @@ -52,17 +53,18 @@ defmodule GithubRepoCloner.ClonerTest do {:ok, %Tesla.Env{status: 404, body: serialized_response_body}} end) - result = Cloner.clone(username) - assert ^result = expected_result + {:error, result} = Cloner.clone_page(%{username: username, page: page}) + assert ^result = "No repositories found" end - test "clone\1: nil" do - result = Cloner.clone(nil) - assert ^result = true + test "clone_page/1: nil username" do + {:error, result} = Cloner.clone_page(%{username: nil, page: nil}) + assert ^result = "No repositories found" end - test "clone\0: valid noop" do - result = Cloner.clone - assert ^result = true + test "clone_page/1: nil page" do + username = "murjax" + {:error, result} = Cloner.clone_page(%{username: username, page: nil}) + assert ^result = "No repositories found" end end diff --git a/elixir/test/page_iterator_test.exs b/elixir/test/page_iterator_test.exs new file mode 100644 index 0000000..551fb79 --- /dev/null +++ b/elixir/test/page_iterator_test.exs @@ -0,0 +1,23 @@ +defmodule GithubRepoCloner.PageIteratorTest do + use ExUnit.Case + alias GithubRepoCloner.PageIterator + + test "repeat/3: Repeat function with next page until it returns an error" do + {:ok, page_reached} = PageIterator.repeat(&TestIteratable.runner/1, %{username: "murjax", page: 1}) + assert ^page_reached = 3 + end +end + +defmodule TestIteratable do + def runner(%{username: username, page: 1}) do + {:ok, username} + end + + def runner(%{username: username, page: 2}) do + {:ok, username} + end + + def runner(%{username: _, page: 3}) do + {:error, "Finished"} + end +end