Skip to content

Commit

Permalink
Merge pull request DiversityTemplating#10 from DiversityTemplating/be…
Browse files Browse the repository at this point in the history
…tter-file-handling

Changed from os:cmd to erlang:open_port so we can stream the result. Thi...
  • Loading branch information
RaoH committed Nov 7, 2014
2 parents 35648d9 + 9f4971a commit e3e3b6c
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 31 deletions.
25 changes: 14 additions & 11 deletions src/component_handler.erl
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
-export([handle/2]).
-export([terminate/3]).

-record(state, {
}).
-record(state, {}).

-define(JSON_HEADER, [{<<"content-type">>, <<"application/json">>}, {<<"Access-Control-Allow-Origin">>, <<"*">>}]).

Expand Down Expand Up @@ -34,10 +33,9 @@ handle_get(Req, _State=#state{}) ->
Tag = expand_tag(PartialTag, Tags),
case Routes of
[] ->
Data = divapi_cache:get_diversity_json(ComponentName, Tag),
case Data of
case divapi_cache:get_diversity_json(ComponentName, Tag) of
undefined -> cowboy_req:reply(404, Req3);
_ -> cowboy_req:reply(200, ?JSON_HEADER, Data, Req3)
Data -> cowboy_req:reply(200, ?JSON_HEADER, Data, Req3)
end;
[Settings] when Settings =:= <<"settings">>;
Settings =:= <<"settingsForm">> ->
Expand All @@ -48,13 +46,19 @@ handle_get(Req, _State=#state{}) ->
cowboy_req:reply(200, ?JSON_HEADER, SettingsJson, Req3);
[<<"files">> | Path] ->
File = filename:join(Path),
FileData = git_utils:get_file(ComponentName, undefined, Tag, File),
{Mime, Type, []} = cow_mimetypes:all(File),
Header = [{<<"content-type">>, << Mime/binary, "/", Type/binary >>}],
cowboy_req:reply(200, Header, FileData, Req3);
FileBin = git_utils:get_file(ComponentName, undefined, Tag, File),
case FileBin of
undefined ->
cowboy_req:reply(404, Req3);
error ->
cowboy_req:reply(500, Req3);
_ ->
{Mime, Type, []} = cow_mimetypes:all(File),
Headers = [{<<"content-type">>, << Mime/binary, "/", Type/binary >>}],
cowboy_req:reply(200, Headers, FileBin, Req3)
end;
_ ->
cowboy_req:reply(404, Req3)

end;
_ ->
cowboy_req:reply(404, Req3)
Expand All @@ -71,7 +75,6 @@ expand_tag(Tag, Tags) ->
<<Tag/binary, ".", PatchNr/binary>>
end.


handle_post(Req, _State=#state{}) ->
{ComponentName, Req2} = cowboy_req:binding(component, Req),
{PathInfo, Req3} = cowboy_req:path_info(Req2),
Expand Down
61 changes: 41 additions & 20 deletions src/git_utils.erl
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@
%% @doc Returns a list with all tags in a git repository
-spec tags(binary(), binary()) -> [binary()].
tags(RepoName, RepoUrl) ->
Cmd = "tag",
ResultString = get_git_result(RepoName, RepoUrl, Cmd),
[list_to_binary(Tag) || Tag <- string:tokens(ResultString, "\n")].
Cmd = <<"git tag">>,
case get_git_result(RepoName, RepoUrl, Cmd) of
error ->
[];
<<>> ->
[];
ResultBin ->
Res = re:split(ResultBin, <<"\n">>),
lists:droplast(Res)
end.

%% @doc Returns the diversity.json for a tag in a repo
-spec get_diversity_json(binary(), binary(), binary()) -> binary().
Expand All @@ -20,48 +27,62 @@ get_diversity_json(RepoName, RepoUrl, Tag) ->
git_refresh_repo(RepoName) ->
{ok, RepoDir} = application:get_env(divapi, repo_dir),
GitRepoName = RepoDir ++ "/" ++ binary_to_list(RepoName) ++ ".git",
file:set_cwd(GitRepoName),
Cmd = "fetch origin master:master",
git_cmd(Cmd).
Cmd = <<"git fetch origin master:master">>,
git_cmd(Cmd, GitRepoName).

get_file(RepoName, RepoUrl, Tag, FilePath) ->
get_git_file(RepoName, RepoUrl, Tag, FilePath).


%% ----------------------------------------------------------------------------
%% Internal stuff
%% ----------------------------------------------------------------------------

%% @doc Retrieves the file from the bare git repo and the specific tag.
-spec get_git_file(RepoName :: binary(), RepoUrl :: binary(), Tag :: binary(),
FilePath :: binary) -> binary() | undefined.
get_git_file(RepoName, RepoUrl, Tag, FilePath) ->
Cmd = "show " ++ binary_to_list(Tag) ++ ":" ++ binary_to_list(FilePath),
Cmd = <<"git --no-pager show ", Tag/binary, ":", FilePath/binary>>,
case get_git_result(RepoName, RepoUrl, Cmd) of
"fatal" ++ _ -> undefined;
Result -> list_to_binary(Result)
FileBin when is_binary(FileBin) -> FileBin;
error -> undefined;
ok -> <<>> %% Command succesful but empty result!
end.

get_git_result(RepoName, RepoUrl, Cmd) ->
{ok, RepoDir} = application:get_env(divapi, repo_dir),
GitRepoName = RepoDir ++ "/" ++ binary_to_list(RepoName) ++ ".git",
GitRepoDir = RepoDir ++ "/" ++ binary_to_list(RepoName) ++ ".git",
%% Clone git repo if non-existing in configured dir
case filelib:is_dir(GitRepoName) of
case filelib:is_dir(GitRepoDir) of
false ->
RepoUrl2 = get_repo_url(RepoName, RepoUrl),
clone_bare(binary_to_list(RepoUrl2));
true ->
%% Checkout not needed
ok
end,
file:set_cwd(GitRepoName),
git_cmd(Cmd).
git_cmd(Cmd, GitRepoDir).

clone_bare(RepoUrl) ->
{ok, RepoDir} = application:get_env(divapi, repo_dir),
filelib:ensure_dir(RepoDir ++ "/"),
file:set_cwd(RepoDir),
Cmd = "clone --bare " ++ RepoUrl,
git_cmd(Cmd).
%% Ensure it exists if not try to create it.
ok = filelib:ensure_dir(RepoDir ++ "/"),
Cmd = <<"git clone --bare ", (list_to_binary(RepoUrl))/binary>>,
git_cmd(Cmd, RepoDir).

get_repo_url(RepoName, undefined) -> gitlab_utils:get_public_project_url(RepoName);
get_repo_url(_, RepoUrl) -> RepoUrl.

git_cmd(Cmd) ->
os:cmd("git " ++ Cmd).
git_cmd(Cmd, WorkingDir) ->
Port = erlang:open_port({spawn, Cmd}, [exit_status, {cd, WorkingDir}, binary, use_stdio]),
wait_for_file(Port, <<>>).

wait_for_file(Port, File) ->
receive
{Port, {data, Chunk}} ->
wait_for_file(Port, <<File/binary, Chunk/binary>>);
{_ , {exit_status, 0}} ->
File;
{_, {exit_status, _}} ->
%% Either not a git repo or operation failed. No need to close port it' already done.
error
end.

0 comments on commit e3e3b6c

Please sign in to comment.