Permalink
Browse files

Added modular indeces support

  • Loading branch information...
1 parent 0fb31bc commit 61c97b0e8b1199a9107a9d53ce6c4d355b87c3e1 @yrashk yrashk committed Jan 25, 2011
Showing with 149 additions and 31 deletions.
  1. +8 −0 include/agner.hrl
  2. +10 −0 include/agner_index.erl
  3. +4 −0 include/agner_index.hrl
  4. +1 −1 src/agner.app.src
  5. +2 −2 src/agner.erl
  6. +81 −14 src/agner_github.erl
  7. +10 −0 src/agner_index.erl
  8. +33 −14 src/agner_server.erl
View
@@ -4,3 +4,11 @@
-type agner_key() :: term().
-type agner_value() :: term().
-type agner_spec() :: list({agner_key(), agner_value()}).
+
+-type agner_repo() :: string().
+-type agner_repo_tag() :: string().
+-type agner_repo_branch() :: string().
+
+-type sha1() :: string().
+
+-type not_found_error() :: {error, not_found}.
View
@@ -0,0 +1,10 @@
+-module(agner_index).
+-export([behaviour_info/1]).
+
+-spec behaviour_info(atom()) -> undefined | list({atom(), arity()}).
+
+behaviour_info(callbacks) ->
+ [{repositories,0}, {tags,1}, {branches, 1}, {spec, 2}}];
+behaviour_info(_Other) ->
+ undefined.
+
View
@@ -0,0 +1,4 @@
+-spec repositories() -> list(agner_repo()) | not_found_error().
+-spec tags(agner_repo()) -> list({agner_repo_tag(),sha1()}) | not_found_error().
+-spec branches(agner_repo()) -> list({agner_repo_branch(), sha1()}) | not_found_error().
+-spec spec(agner_repo(), sha1()) -> agner_spec() | not_found_error().
View
@@ -8,7 +8,7 @@
stdlib,
inets
]},
- {env, [{indexes, [{github, "agner"}]}]},
+ {env, [{indeces, [{github, "agner"}]}]},
{mod, { agner_app, []}},
{env, []}
]}.
View
@@ -23,8 +23,8 @@ main(_) ->
%%%===================================================================
%%% API
%%%===================================================================
--spec spec(agner_spec_name()) -> agner_spec().
--spec spec(agner_spec_name(), agner_spec_version()) -> agner_spec().
+-spec spec(agner_spec_name()) -> agner_spec() | not_found_error().
+-spec spec(agner_spec_name(), agner_spec_version()) -> agner_spec() | not_found_error().
spec(Name) ->
spec(Name, master).
View
@@ -1,21 +1,73 @@
-module(agner_github, [Account]).
--export([list_all_repos/0,
- list_tags/1,
- list_branches/1,
- blob/3
+-behaviour(agner_index).
+-include_lib("agner.hrl").
+-include_lib("agner_index.hrl").
+
+-export([repositories/0,
+ repository/1,
+ tags/1,
+ branches/1,
+ spec/2
]).
-list_all_repos() ->
- request("https://github.com/api/v2/json/repos/show/" ++ Account).
+repositories() ->
+ case request("https://github.com/api/v2/json/repos/show/" ++ Account) of
+ {error, _Reason} = Error ->
+ Error;
+ {struct, Object} ->
+ Repositories = proplists:get_value(<<"repositories">>, Object),
+ lists:all(fun (invalid) ->
+ false;
+ (_) ->
+ true
+ end,
+ lists:map(fun ({struct, RepObject}) ->
+ repo_name(proplists:get_value(<<"name">>, RepObject))
+ end, Repositories))
+ end.
+
+repository(Name) ->
+ case request("https://github.com/api/v2/json/repos/show/" ++ Account ++ "/" ++ Name ++ ".agner") of
+ {error, _Reason} = Error ->
+ Error;
+ {struct, Object} ->
+ {struct, Repo} = proplists:get_value(<<"repository">>, Object),
+ Repo
+ end.
+
-list_tags(Name) ->
- request("http://github.com/api/v2/json/repos/show/" ++ Account ++ "/" ++ Name ++ "/tags").
+tags(Name) ->
+ case request("http://github.com/api/v2/json/repos/show/" ++ Account ++ "/" ++ Name ++ ".agner/tags") of
+ {struct, Object} ->
+ {struct, Tags} = proplists:get_value(<<"tags">>, Object),
+ lists:map(fun({Tag, SHA1}) ->
+ {binary_to_list(Tag),
+ binary_to_list(SHA1)}
+ end, Tags)
+ end.
+
+
+branches(Name) ->
+ case request("http://github.com/api/v2/json/repos/show/" ++ Account ++ "/" ++ Name ++ ".agner/branches") of
+ {error, _Reason} = Error ->
+ Error;
+ {struct, Object} ->
+ {struct, Branches} = proplists:get_value(<<"branches">>, Object),
+ lists:map(fun({Branch, SHA1}) ->
+ {binary_to_list(Branch),
+ binary_to_list(SHA1)}
+ end, Branches)
+ end.
-list_branches(Name) ->
- request("http://github.com/api/v2/json/repos/show/" ++ Account ++ "/" ++ Name ++ "/branches").
+spec(Name, SHA1) ->
+ case request("http://github.com/api/v2/json/blob/show/" ++ Account ++ "/" ++ Name ++ ".agner/" ++ SHA1 ++ "/agner.config") of
+ {error, _Reason} = Error ->
+ Error;
+ {struct, Object} ->
+ {struct, Blob} = proplists:get_value(<<"blob">>, Object),
+ binary_to_list(proplists:get_value(<<"data">>, Blob))
+ end.
-blob(Name, SHA1, Path) ->
- request("http://github.com/api/v2/json/blob/show/" ++ Account ++ "/" ++ Name ++ "/" ++ SHA1 ++ "/" ++ Path).
%%%
@@ -31,5 +83,20 @@ httpc_request_1(URL, Opts) ->
[{timeout, 60000}],
Opts,
agner).
-parse_response({ok, {{"HTTP/1.1",200,_},_Header,Body}}) ->
- mochijson2:decode(Body).
+
+parse_response({ok, {{"HTTP/1.1",200,_},_Headers,Body}}) ->
+ mochijson2:decode(Body);
+parse_response({ok, {{"HTTP/1.1",404,_},_Headers,_Body}}) ->
+ {error, not_found}.
+
+%%%
+
+repo_name(B) when is_binary(B) ->
+ S = binary_to_list(B),
+ case string:tokens(S,".") of
+ [Name,"agner"] ->
+ Name;
+ _ ->
+ invalid
+ end.
+
View
@@ -0,0 +1,10 @@
+-module(agner_index).
+-export([behaviour_info/1]).
+
+-spec behaviour_info(atom()) -> undefined | list({atom(), arity()}).
+
+behaviour_info(callbacks) ->
+ [{repositories,0}, {repository, 1}, {tags,1}, {branches, 1}, {spec, 2}];
+behaviour_info(_Other) ->
+ undefined.
+
View
@@ -70,21 +70,16 @@ init([]) ->
-spec handle_call(agner_call_spec(), gen_server_from(), gen_server_state()) ->
gen_server_async_reply(agner_spec()).
-handle_call({spec, Name0, Version}, From, #state{}=State) ->
- Name = Name0 ++ ".agner",
+handle_call({spec, Name, Version}, From, #state{}=State) ->
spawn_link(fun () ->
- SHA1 =
- case Version of
- master ->
- {struct, [{<<"branches">>, {struct, PL}}]} = agner_github:list_branches(Name),
- binary_to_list(proplists:get_value(<<"master">>, PL));
- _ ->
- {struct, [{<<"tags">>, {struct, PL}}]} = agner_github:list_tags(Name),
- binary_to_list(proplists:get_value(list_to_binary(Name), PL))
- end,
- {struct, [{<<"blob">>, {struct, PL1}}]} = agner_github:blob(Name, SHA1, "agner.config"),
- Data = proplists:get_value(<<"data">>, PL1),
- gen_server:reply(From, Data)
+ Indeces =
+ case application:get_env(indeces) of
+ {ok, Val} ->
+ Val;
+ undefined ->
+ []
+ end,
+ handle_spec(Name, Version, From, Indeces)
end),
{noreply, State}.
@@ -146,3 +141,27 @@ code_change(_OldVsn, State, _Extra) ->
%%%===================================================================
%%% Internal functions
%%%===================================================================
+-spec handle_spec(agner_spec_name(), agner_spec_version(), gen_server_from(), list(tuple())) -> any().
+handle_spec(_,_,From,[]) ->
+ gen_server:reply(From, {error, not_found});
+handle_spec(Name, Version, From, [Mod0|Rest]) ->
+ Mod = index_module(Mod0),
+ case Mod:repository(Name) of
+ {error, not_found} ->
+ handle_spec(Name, Version, From, Rest);
+ _ ->
+ SHA1 =
+ case Version of
+ master ->
+ Branches = Mod:branches(Name),
+ proplists:get_value("master", Branches);
+ _ ->
+ Tags = Mod:tags(Name),
+ proplists:get_value(Version, Tags)
+ end,
+ Data = Mod:spec(Name, SHA1),
+ gen_server:reply(From, Data)
+ end.
+
+index_module({github, Account}) ->
+ {agner_github, Account}.

0 comments on commit 61c97b0

Please sign in to comment.