|
@ -7,256 +7,25 @@ |
|
|
%% ------------------------------------------------------------------- |
|
|
%% ------------------------------------------------------------------- |
|
|
-module(rebar_fetch). |
|
|
-module(rebar_fetch). |
|
|
|
|
|
|
|
|
-export([new/4, |
|
|
|
|
|
lock_source/2, |
|
|
|
|
|
download_source/2, |
|
|
|
|
|
update_source1/2, |
|
|
|
|
|
source_engine_avail/1, |
|
|
|
|
|
source_engine_avail/2, |
|
|
|
|
|
has_vcs_dir/2, |
|
|
|
|
|
print_source/1, |
|
|
|
|
|
format_source/2]). |
|
|
|
|
|
|
|
|
-export([lock_source/2, |
|
|
|
|
|
download_source/2]). |
|
|
|
|
|
|
|
|
-include("rebar.hrl"). |
|
|
-include("rebar.hrl"). |
|
|
|
|
|
|
|
|
-record(p4_settings, { |
|
|
|
|
|
client=undefined, |
|
|
|
|
|
transport="tcp4:perforce:1666", |
|
|
|
|
|
username, |
|
|
|
|
|
password |
|
|
|
|
|
}). |
|
|
|
|
|
|
|
|
|
|
|
new(Dir, App, Vsn, Source) -> |
|
|
|
|
|
NewSource = lock_source(Dir, Source), |
|
|
|
|
|
{App, Vsn, NewSource}. |
|
|
|
|
|
|
|
|
|
|
|
init_p4_settings(Basename) -> |
|
|
|
|
|
#p4_settings{client = |
|
|
|
|
|
case inet:gethostname() of |
|
|
|
|
|
{ok,HostName} -> |
|
|
|
|
|
HostName ++ "-" |
|
|
|
|
|
++ os:getenv("USER") ++ "-" |
|
|
|
|
|
++ Basename |
|
|
|
|
|
++ "-Rebar-automated-download" |
|
|
|
|
|
end}. |
|
|
|
|
|
|
|
|
|
|
|
lock_source(AppDir, {git, Url, _}) -> |
|
|
|
|
|
Ref = string:strip(os:cmd("git --git-dir='" ++ AppDir ++ "/.git' rev-parse --verify HEAD"), both, $\n), |
|
|
|
|
|
{git, Url, Ref}; |
|
|
|
|
|
lock_source(_AppDir, Source) -> |
|
|
|
|
|
Source. |
|
|
|
|
|
|
|
|
lock_source(AppDir, Source) -> |
|
|
|
|
|
rebar_git_resource:lock(AppDir, Source). |
|
|
|
|
|
|
|
|
download_source(AppDir, Source) -> |
|
|
download_source(AppDir, Source) -> |
|
|
TmpDir = ec_file:insecure_mkdtemp(), |
|
|
TmpDir = ec_file:insecure_mkdtemp(), |
|
|
AppDir1 = ec_cnv:to_list(AppDir), |
|
|
AppDir1 = ec_cnv:to_list(AppDir), |
|
|
ec_file:mkdir_p(AppDir1), |
|
|
ec_file:mkdir_p(AppDir1), |
|
|
case download_source_tmp(TmpDir, Source) of |
|
|
|
|
|
|
|
|
case rebar_git_resource:download(TmpDir, Source) of |
|
|
{ok, _} -> |
|
|
{ok, _} -> |
|
|
ok = ec_file:copy(TmpDir, filename:absname(AppDir1), [recursive]); |
|
|
ok = ec_file:copy(TmpDir, filename:absname(AppDir1), [recursive]); |
|
|
{tarball, File} -> |
|
|
{tarball, File} -> |
|
|
ok = erl_tar:extract(File, [{cwd, TmpDir} |
|
|
ok = erl_tar:extract(File, [{cwd, TmpDir} |
|
|
,compressed]), |
|
|
|
|
|
|
|
|
,compressed]), |
|
|
BaseName = filename:basename(AppDir1), |
|
|
BaseName = filename:basename(AppDir1), |
|
|
[FromDir] = filelib:wildcard(filename:join(TmpDir, BaseName++"-*")), |
|
|
[FromDir] = filelib:wildcard(filename:join(TmpDir, BaseName++"-*")), |
|
|
ec_file:copy(FromDir, AppDir1, [recursive]) |
|
|
ec_file:copy(FromDir, AppDir1, [recursive]) |
|
|
end. |
|
|
end. |
|
|
|
|
|
|
|
|
download_source_tmp(TmpDir, {p4, Url}) -> |
|
|
|
|
|
download_source_tmp(TmpDir, {p4, Url, "#head"}); |
|
|
|
|
|
download_source_tmp(TmpDir, {p4, Url, Rev}) -> |
|
|
|
|
|
download_source_tmp(TmpDir, {p4, Url, Rev, init_p4_settings(filename:basename(TmpDir))}); |
|
|
|
|
|
download_source_tmp(TmpDir, {p4, Url, _Rev, Settings}) -> |
|
|
|
|
|
ok = filelib:ensure_dir(TmpDir), |
|
|
|
|
|
rebar_utils:sh_send("p4 client -i", |
|
|
|
|
|
?FMT("Client: ~s~n" |
|
|
|
|
|
++"Description: generated by Rebar~n" |
|
|
|
|
|
++"Root: ~s~n" |
|
|
|
|
|
++"View:~n" |
|
|
|
|
|
++" ~s/... //~s/...~n", |
|
|
|
|
|
[Settings#p4_settings.client, |
|
|
|
|
|
TmpDir, |
|
|
|
|
|
Url, |
|
|
|
|
|
Settings#p4_settings.client]), |
|
|
|
|
|
[]), |
|
|
|
|
|
rebar_utils:sh(?FMT("p4 -c ~s sync -f", [Settings#p4_settings.client]), []); |
|
|
|
|
|
download_source_tmp(TmpDir, {hg, Url, Rev}) -> |
|
|
|
|
|
ok = filelib:ensure_dir(TmpDir), |
|
|
|
|
|
rebar_utils:sh(?FMT("hg clone -U ~s ~s", [Url, filename:basename(TmpDir)]), |
|
|
|
|
|
[{cd, filename:dirname(TmpDir)}]), |
|
|
|
|
|
rebar_utils:sh(?FMT("hg update ~s", [Rev]), [{cd, TmpDir}]); |
|
|
|
|
|
download_source_tmp(TmpDir, {git, Url}) -> |
|
|
|
|
|
download_source_tmp(TmpDir, {git, Url, {branch, "HEAD"}}); |
|
|
|
|
|
download_source_tmp(TmpDir, {git, Url, ""}) -> |
|
|
|
|
|
download_source_tmp(TmpDir, {git, Url, {branch, "HEAD"}}); |
|
|
|
|
|
download_source_tmp(TmpDir, {git, Url, {branch, Branch}}) -> |
|
|
|
|
|
ok = filelib:ensure_dir(TmpDir), |
|
|
|
|
|
rebar_utils:sh(?FMT("git clone -n ~s ~s", [Url, filename:basename(TmpDir)]), |
|
|
|
|
|
[{cd, filename:dirname(TmpDir)}]), |
|
|
|
|
|
rebar_utils:sh(?FMT("git checkout -q origin/~s", [Branch]), [{cd, TmpDir}]); |
|
|
|
|
|
download_source_tmp(TmpDir, {git, Url, {tag, Tag}}) -> |
|
|
|
|
|
ok = filelib:ensure_dir(TmpDir), |
|
|
|
|
|
rebar_utils:sh(?FMT("git clone -n ~s ~s", [Url, filename:basename(TmpDir)]), |
|
|
|
|
|
[{cd, filename:dirname(TmpDir)}]), |
|
|
|
|
|
rebar_utils:sh(?FMT("git checkout -q ~s", [Tag]), [{cd, TmpDir}]); |
|
|
|
|
|
download_source_tmp(TmpDir, {git, Url, Rev}) -> |
|
|
|
|
|
ok = filelib:ensure_dir(TmpDir), |
|
|
|
|
|
rebar_utils:sh(?FMT("git clone -n ~s ~s", [Url, filename:basename(TmpDir)]), |
|
|
|
|
|
[{cd, filename:dirname(TmpDir)}]), |
|
|
|
|
|
rebar_utils:sh(?FMT("git checkout -q ~s", [Rev]), [{cd, TmpDir}]); |
|
|
|
|
|
download_source_tmp(TmpDir, {bzr, Url, Rev}) -> |
|
|
|
|
|
ok = filelib:ensure_dir(TmpDir), |
|
|
|
|
|
rebar_utils:sh(?FMT("bzr branch -r ~s ~s ~s", |
|
|
|
|
|
[Rev, Url, filename:basename(TmpDir)]), |
|
|
|
|
|
[{cd, filename:dirname(TmpDir)}]); |
|
|
|
|
|
download_source_tmp(TmpDir, {svn, Url, Rev}) -> |
|
|
|
|
|
ok = filelib:ensure_dir(TmpDir), |
|
|
|
|
|
rebar_utils:sh(?FMT("svn checkout -r ~s ~s ~s", |
|
|
|
|
|
[Rev, Url, filename:basename(TmpDir)]), |
|
|
|
|
|
[{cd, filename:dirname(TmpDir)}]); |
|
|
|
|
|
download_source_tmp(TmpDir, {rsync, Url}) -> |
|
|
|
|
|
ok = filelib:ensure_dir(TmpDir), |
|
|
|
|
|
rebar_utils:sh(?FMT("rsync -az --delete ~s/ ~s", [Url, TmpDir]), []); |
|
|
|
|
|
download_source_tmp(TmpDir, {fossil, Url}) -> |
|
|
|
|
|
download_source_tmp(TmpDir, {fossil, Url, ""}); |
|
|
|
|
|
download_source_tmp(TmpDir, {fossil, Url, Version}) -> |
|
|
|
|
|
Repository = filename:join(TmpDir, filename:basename(TmpDir) ++ ".fossil"), |
|
|
|
|
|
ok = filelib:ensure_dir(Repository), |
|
|
|
|
|
ok = file:set_cwd(TmpDir), |
|
|
|
|
|
rebar_utils:sh(?FMT("fossil clone ~s ~s", [Url, Repository]), |
|
|
|
|
|
[{cd, TmpDir}]), |
|
|
|
|
|
rebar_utils:sh(?FMT("fossil open ~s ~s --nested", [Repository, Version]), |
|
|
|
|
|
[]); |
|
|
|
|
|
download_source_tmp(TmpDir, Url) -> |
|
|
|
|
|
TmpFile = filename:join(TmpDir, "package.tar.gz"), |
|
|
|
|
|
{ok, saved_to_file} = httpc:request(get, {binary_to_list(Url), []}, [], [{stream, TmpFile}]), |
|
|
|
|
|
{tarball, TmpFile}. |
|
|
|
|
|
|
|
|
|
|
|
update_source1(AppDir, Args) when element(1, Args) =:= p4 -> |
|
|
|
|
|
download_source_tmp(AppDir, Args); |
|
|
|
|
|
update_source1(AppDir, {git, Url}) -> |
|
|
|
|
|
update_source1(AppDir, {git, Url, {branch, "HEAD"}}); |
|
|
|
|
|
update_source1(AppDir, {git, Url, ""}) -> |
|
|
|
|
|
update_source1(AppDir, {git, Url, {branch, "HEAD"}}); |
|
|
|
|
|
update_source1(AppDir, {git, _Url, {branch, Branch}}) -> |
|
|
|
|
|
ShOpts = [{cd, AppDir}], |
|
|
|
|
|
rebar_utils:sh("git fetch origin", ShOpts), |
|
|
|
|
|
rebar_utils:sh(?FMT("git checkout -q ~s", [Branch]), ShOpts), |
|
|
|
|
|
rebar_utils:sh( |
|
|
|
|
|
?FMT("git pull --ff-only --no-rebase -q origin ~s", [Branch]),ShOpts); |
|
|
|
|
|
update_source1(AppDir, {git, _Url, {tag, Tag}}) -> |
|
|
|
|
|
ShOpts = [{cd, AppDir}], |
|
|
|
|
|
rebar_utils:sh("git fetch origin", ShOpts), |
|
|
|
|
|
rebar_utils:sh(?FMT("git checkout -q ~s", [Tag]), ShOpts); |
|
|
|
|
|
update_source1(AppDir, {git, _Url, Refspec}) -> |
|
|
|
|
|
ShOpts = [{cd, AppDir}], |
|
|
|
|
|
rebar_utils:sh("git fetch origin", ShOpts), |
|
|
|
|
|
rebar_utils:sh(?FMT("git checkout -q ~s", [Refspec]), ShOpts); |
|
|
|
|
|
update_source1(AppDir, {svn, _Url, Rev}) -> |
|
|
|
|
|
rebar_utils:sh(?FMT("svn up -r ~s", [Rev]), [{cd, AppDir}]); |
|
|
|
|
|
update_source1(AppDir, {hg, _Url, Rev}) -> |
|
|
|
|
|
rebar_utils:sh(?FMT("hg pull -u -r ~s", [Rev]), [{cd, AppDir}]); |
|
|
|
|
|
update_source1(AppDir, {bzr, _Url, Rev}) -> |
|
|
|
|
|
rebar_utils:sh(?FMT("bzr update -r ~s", [Rev]), [{cd, AppDir}]); |
|
|
|
|
|
update_source1(AppDir, {rsync, Url}) -> |
|
|
|
|
|
rebar_utils:sh(?FMT("rsync -az --delete ~s/ ~s",[Url,AppDir]),[]); |
|
|
|
|
|
update_source1(AppDir, {fossil, Url}) -> |
|
|
|
|
|
update_source1(AppDir, {fossil, Url, ""}); |
|
|
|
|
|
update_source1(AppDir, {fossil, _Url, Version}) -> |
|
|
|
|
|
ok = file:set_cwd(AppDir), |
|
|
|
|
|
rebar_utils:sh("fossil pull", [{cd, AppDir}]), |
|
|
|
|
|
rebar_utils:sh(?FMT("fossil update ~s", [Version]), []). |
|
|
|
|
|
|
|
|
|
|
|
%% =================================================================== |
|
|
|
|
|
%% Source helper functions |
|
|
|
|
|
%% =================================================================== |
|
|
|
|
|
|
|
|
|
|
|
source_engine_avail(Source) -> |
|
|
|
|
|
Name = element(1, Source), |
|
|
|
|
|
source_engine_avail(Name, Source). |
|
|
|
|
|
|
|
|
|
|
|
source_engine_avail(Name, Source) |
|
|
|
|
|
when Name == hg; Name == git; Name == svn; Name == bzr; Name == rsync; |
|
|
|
|
|
Name == fossil; Name == p4 -> |
|
|
|
|
|
case vcs_client_vsn(Name) >= required_vcs_client_vsn(Name) of |
|
|
|
|
|
true -> |
|
|
|
|
|
true; |
|
|
|
|
|
false -> |
|
|
|
|
|
?ABORT("Rebar requires version ~p or higher of ~s to process ~p\n", |
|
|
|
|
|
[required_vcs_client_vsn(Name), Name, Source]) |
|
|
|
|
|
end. |
|
|
|
|
|
|
|
|
|
|
|
vcs_client_vsn(false, _VsnArg, _VsnRegex) -> |
|
|
|
|
|
false; |
|
|
|
|
|
vcs_client_vsn(Path, VsnArg, VsnRegex) -> |
|
|
|
|
|
{ok, Info} = rebar_utils:sh(Path ++ VsnArg, [{env, [{"LANG", "C"}]}, |
|
|
|
|
|
{use_stdout, false}]), |
|
|
|
|
|
case re:run(Info, VsnRegex, [{capture, all_but_first, list}]) of |
|
|
|
|
|
{match, Match} -> |
|
|
|
|
|
list_to_tuple([list_to_integer(S) || S <- Match]); |
|
|
|
|
|
_ -> |
|
|
|
|
|
false |
|
|
|
|
|
end. |
|
|
|
|
|
|
|
|
|
|
|
required_vcs_client_vsn(p4) -> {2013, 1}; |
|
|
|
|
|
required_vcs_client_vsn(hg) -> {1, 1}; |
|
|
|
|
|
required_vcs_client_vsn(git) -> {1, 5}; |
|
|
|
|
|
required_vcs_client_vsn(bzr) -> {2, 0}; |
|
|
|
|
|
required_vcs_client_vsn(svn) -> {1, 6}; |
|
|
|
|
|
required_vcs_client_vsn(rsync) -> {2, 0}; |
|
|
|
|
|
required_vcs_client_vsn(fossil) -> {1, 0}. |
|
|
|
|
|
|
|
|
|
|
|
vcs_client_vsn(p4) -> |
|
|
|
|
|
vcs_client_vsn(rebar_utils:find_executable("p4"), " -V", |
|
|
|
|
|
"Rev\\. .*/(\\d+)\\.(\\d)/"); |
|
|
|
|
|
vcs_client_vsn(hg) -> |
|
|
|
|
|
vcs_client_vsn(rebar_utils:find_executable("hg"), " --version", |
|
|
|
|
|
"version (\\d+).(\\d+)"); |
|
|
|
|
|
vcs_client_vsn(git) -> |
|
|
|
|
|
vcs_client_vsn(rebar_utils:find_executable("git"), " --version", |
|
|
|
|
|
"git version (\\d+).(\\d+)"); |
|
|
|
|
|
vcs_client_vsn(bzr) -> |
|
|
|
|
|
vcs_client_vsn(rebar_utils:find_executable("bzr"), " --version", |
|
|
|
|
|
"Bazaar \\(bzr\\) (\\d+).(\\d+)"); |
|
|
|
|
|
vcs_client_vsn(svn) -> |
|
|
|
|
|
vcs_client_vsn(rebar_utils:find_executable("svn"), " --version", |
|
|
|
|
|
"svn, version (\\d+).(\\d+)"); |
|
|
|
|
|
vcs_client_vsn(rsync) -> |
|
|
|
|
|
vcs_client_vsn(rebar_utils:find_executable("rsync"), " --version", |
|
|
|
|
|
"rsync version (\\d+).(\\d+)"); |
|
|
|
|
|
vcs_client_vsn(fossil) -> |
|
|
|
|
|
vcs_client_vsn(rebar_utils:find_executable("fossil"), " version", |
|
|
|
|
|
"version (\\d+).(\\d+)"). |
|
|
|
|
|
|
|
|
|
|
|
has_vcs_dir(p4, _) -> |
|
|
|
|
|
true; |
|
|
|
|
|
has_vcs_dir(git, Dir) -> |
|
|
|
|
|
filelib:is_dir(filename:join(Dir, ".git")); |
|
|
|
|
|
has_vcs_dir(hg, Dir) -> |
|
|
|
|
|
filelib:is_dir(filename:join(Dir, ".hg")); |
|
|
|
|
|
has_vcs_dir(bzr, Dir) -> |
|
|
|
|
|
filelib:is_dir(filename:join(Dir, ".bzr")); |
|
|
|
|
|
has_vcs_dir(svn, Dir) -> |
|
|
|
|
|
filelib:is_dir(filename:join(Dir, ".svn")) |
|
|
|
|
|
orelse filelib:is_dir(filename:join(Dir, "_svn")); |
|
|
|
|
|
has_vcs_dir(rsync, _) -> |
|
|
|
|
|
true; |
|
|
|
|
|
has_vcs_dir(_, _) -> |
|
|
|
|
|
true. |
|
|
|
|
|
|
|
|
|
|
|
print_source({App, _, Source}) -> |
|
|
|
|
|
?CONSOLE("~s~n", [format_source(App, Source)]). |
|
|
|
|
|
|
|
|
|
|
|
format_source(App, {p4, Url}) -> |
|
|
|
|
|
format_source(App, {p4, Url, "#head"}); |
|
|
|
|
|
format_source(App, {git, Url}) -> |
|
|
|
|
|
?FMT("~p BRANCH ~s ~s", [App, "HEAD", Url]); |
|
|
|
|
|
format_source(App, {git, Url, ""}) -> |
|
|
|
|
|
?FMT("~p BRANCH ~s ~s", [App, "HEAD", Url]); |
|
|
|
|
|
format_source(App, {git, Url, {branch, Branch}}) -> |
|
|
|
|
|
?FMT("~p BRANCH ~s ~s", [App, Branch, Url]); |
|
|
|
|
|
format_source(App, {git, Url, {tag, Tag}}) -> |
|
|
|
|
|
?FMT("~p TAG ~s ~s", [App, Tag, Url]); |
|
|
|
|
|
format_source(App, {_, Url, Rev}) -> |
|
|
|
|
|
?FMT("~p REV ~s ~s", [App, Rev, Url]); |
|
|
|
|
|
format_source(App, undefined) -> |
|
|
|
|
|
?FMT("~p", [App]). |
|
|
|