%%% BEGIN openflax/handler/svn.erl %%%
%%%
%%% openflax - Open Source web server for Erlang/OTP
%%% Copyright (c)2004 Cat's Eye Technologies. All rights reserved.
%%%
%%% Redistribution and use in source and binary forms, with or without
%%% modification, are permitted provided that the following conditions
%%% are met:
%%%
%%% Redistributions of source code must retain the above copyright
%%% notice, this list of conditions and the following disclaimer.
%%%
%%% Redistributions in binary form must reproduce the above copyright
%%% notice, this list of conditions and the following disclaimer in
%%% the documentation and/or other materials provided with the
%%% distribution.
%%%
%%% Neither the name of Cat's Eye Technologies nor the names of its
%%% contributors may be used to endorse or promote products derived
%%% from this software without specific prior written permission.
%%%
%%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
%%% CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
%%% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
%%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
%%% DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
%%% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
%%% OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
%%% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
%%% OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
%%% ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
%%% OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
%%% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
%%% POSSIBILITY OF SUCH DAMAGE.
%% @doc Subverlsion handler for OpenFlax.
%%
%%
Browse a Subversion repository.
%%
%%
%%
cfg_svn_repo_site
%%
cfg_svn_repo_base
%%
cfg_svn_repo_root
%%
cfg_template_body
%%
cfg_svn_template_each_file
%%
cfg_svn_template_each_subdir
%%
cfg_svn_template_each_link
%%
cfg_svn_template_each_log_entry
%%
cfg_svn_template_each_diff_filename
%%
cfg_svn_template_each_diff_offset
%%
cfg_svn_template_each_diff_unchanged
%%
cfg_svn_template_each_diff_addline
%%
cfg_svn_template_each_diff_removeline
%%
cfg_svn_list_headings
%%
cfg_svn_log_headings
%%
cfg_svn_diff_headings
%%
%%
%% @end
-module(openflax.handler.svn).
-vsn('$Id: svn.erl 35 2004-09-19 21:28:09Z catseye $').
-author('cpressey@catseye.mine.nu').
-copyright('Copyright (c)2004 Cat`s Eye Technologies. All rights reserved.').
-behaviour(openflax.handler).
-export([start/1, stop/1, serve/1]). % behaviour
-import(lists).
-import(string).
-import(filename).
-import(file).
-import(svn).
%% @spec start(conf()) -> conf()
%% @doc Initializes the Subverlsion handler.
start(_Conf) ->
openflax.conf:new().
%% @spec stop(conf()) -> conf()
%% @doc Shuts down the Subverlsion handler.
stop(Conf) ->
Conf.
%% @spec serve(conf()) -> ok | {error, Reason}
%% @doc Serves any of a number of things from a Subversion
%% repository. Currently this includes: the youngest revision
%% of a file, file listings for directories in the repository, and
%% the change log for each file (currently rather crude.)
serve(Conf) ->
URI = openflax.conf:get_string(sreq_basic_resource, Conf),
Branch = case openflax.conf:get_string(arg_branch, Conf) of
"" -> "current";
Else -> Else
end,
% Get the repo base - this is where the repository roots are stored.
RepoSite = openflax.conf:get_string(cfg_svn_repo_site, Conf),
RepoBase = openflax.conf:get_string(cfg_svn_repo_base, Conf),
RepoRoot = openflax.conf:get_string(cfg_svn_repo_root, Conf),
% Turn the URI into a repository name and a file name.
% /repo/project/src/foo.c -> svn://site/base/project/branch/src/foo.c
["/", WebRepoIndex, RepoName | Rest] = filename:split(URI),
Path = filename:join(["/"] ++ Rest),
FilePath = filename:join(["/", Branch] ++ Rest),
% Before anything else, check to see if arg_path was given, and if so, redirect.
case openflax.conf:get_string(arg_path, Conf) of
"" ->
serve0(Conf, URI, Branch, RepoSite, RepoBase, RepoRoot, RepoName, Path, FilePath);
NewPath ->
NewPath0 = "/" ++ WebRepoIndex ++ "/" ++ RepoName ++ NewPath ++ "?" ++
reassemble_args(Conf, [branch, rev, log, base, sortby, keyword]),
{{moved_permanently, NewPath0}, Conf}
end.
serve0(Conf, URI, Branch, RepoSite, RepoBase, RepoRoot, RepoName, Path, FilePath) ->
Repo = svn:open("svn://" ++ RepoSite ++ RepoBase ++ RepoName),
% Determine the desired revision.
HeadRev = svn:head(Repo),
{IsHead, Rev} = case openflax.conf:get_string(arg_rev, Conf) of
"" ->
{true, HeadRev};
RevStr ->
case catch list_to_integer(RevStr) of
RevInt when is_integer(RevInt), RevInt > 0, RevInt < HeadRev ->
{false, RevInt};
_ ->
{true, HeadRev}
end
end,
Conf0 = openflax.conf:put_value(tpl_svn_repository, RepoName, Conf),
Conf1 = openflax.conf:put_value(tpl_svn_path, Path, Conf0),
Conf2 = openflax.conf:put_value(tpl_svn_branch, Branch, Conf1),
Conf3 = openflax.conf:put_value(tpl_svn_rev, openflax.string:from_term(Rev), Conf2),
NextRevLink = case HeadRev == Rev of
true -> "";
false -> ">>"
end,
PrevRevLink = case Rev == 1 of
true -> "";
false -> "<<"
end,
Conf4 = openflax.conf:put_value(tpl_svn_prev_rev_link, PrevRevLink, Conf3),
Conf5 = openflax.conf:put_value(tpl_svn_next_rev_link, NextRevLink, Conf4),
Branches = svn:list(Repo, "/", Rev),
BranchOptions = lists:flatten(lists:map(
fun({BranchName, _BranchType, _BranchRev, _BranchBlame, _BranchSize, _BranchDate}) ->
case BranchName of
Branch ->
[""];
_ ->
[""]
end
end, Branches)),
BranchReleases = lists:flatten(lists:map(
fun({BranchName, _BranchType, _BranchRev, _BranchBlame, _BranchSize, _BranchDate}) ->
case BranchName of
"current" ->
[];
_ ->
ArchiveBaseName = [RepoName, "-", BranchName],
["