Переглянути джерело

fix lock provider to work anytime it is run

pull/31/head
Tristan Sloughter 10 роки тому
джерело
коміт
bdd5d902d9
6 змінених файлів з 138 додано та 154 видалено
  1. +2
    -7
      src/rebar_base_compiler.erl
  2. +27
    -39
      src/rebar_fetch.erl
  3. +1
    -1
      src/rebar_plugins.erl
  4. +84
    -60
      src/rebar_prv_install_deps.erl
  5. +5
    -11
      src/rebar_prv_lock.erl
  6. +19
    -36
      src/rebar_state.erl

+ 2
- 7
src/rebar_base_compiler.erl Переглянути файл

@ -258,10 +258,5 @@ format_error(AbsSource, Extra, {Mod, Desc}) ->
ErrorDesc = Mod:format_error(Desc),
?FMT("~s: ~s~s~n", [AbsSource, Extra, ErrorDesc]).
maybe_absname(Config, Filename) ->
case rebar_utils:processing_base_dir(Config) of
true ->
Filename;
false ->
filename:absname(Filename)
end.
maybe_absname(_Config, Filename) ->
Filename.

+ 27
- 39
src/rebar_fetch.erl Переглянути файл

@ -19,52 +19,40 @@
-spec lock_source(file:filename_all(), rebar_resource:resource()) ->
rebar_resource:resource() | {error, string()}.
lock_source(AppDir, Source) ->
case get_resource_type(Source) of
{error, _}=Error ->
Error;
Module ->
Module:lock(AppDir, Source)
end.
Module = get_resource_type(Source),
Module:lock(AppDir, Source).
-spec download_source(file:filename_all(), rebar_resource:resource()) -> true | {error, any()}.
download_source(AppDir, Source) ->
case get_resource_type(Source) of
{error, _}=Error ->
Error;
Module ->
TmpDir = ec_file:insecure_mkdtemp(),
AppDir1 = ec_cnv:to_list(AppDir),
ec_file:mkdir_p(AppDir1),
case Module:download(TmpDir, Source) of
{ok, _} ->
code:del_path(filename:absname(filename:join(AppDir1, "ebin"))),
ec_file:remove(filename:absname(AppDir1), [recursive]),
ok = ec_file:copy(TmpDir, filename:absname(AppDir1), [recursive]),
true;
{tarball, File} ->
ok = erl_tar:extract(File, [{cwd, TmpDir}
,compressed]),
BaseName = filename:basename(AppDir1),
[FromDir] = filelib:wildcard(filename:join(TmpDir, BaseName++"-*")),
code:del_path(filename:absname(filename:join(AppDir1, "ebin"))),
ec_file:remove(filename:absname(AppDir1), [recursive]),
ok = ec_file:copy(FromDir, filename:absname(AppDir1), [recursive]),
true
end
Module = get_resource_type(Source),
TmpDir = ec_file:insecure_mkdtemp(),
AppDir1 = ec_cnv:to_list(AppDir),
ec_file:mkdir_p(AppDir1),
case Module:download(TmpDir, Source) of
{ok, _} ->
code:del_path(filename:absname(filename:join(AppDir1, "ebin"))),
ec_file:remove(filename:absname(AppDir1), [recursive]),
ok = ec_file:copy(TmpDir, filename:absname(AppDir1), [recursive]),
true;
{tarball, File} ->
ok = erl_tar:extract(File, [{cwd, TmpDir}
,compressed]),
BaseName = filename:basename(AppDir1),
[FromDir] = filelib:wildcard(filename:join(TmpDir, BaseName++"-*")),
code:del_path(filename:absname(filename:join(AppDir1, "ebin"))),
ec_file:remove(filename:absname(AppDir1), [recursive]),
ok = ec_file:copy(FromDir, filename:absname(AppDir1), [recursive]),
true
end.
-spec needs_update(file:filename_all(), rebar_resource:resource()) -> boolean() | {error, string()}.
needs_update(AppDir, Source) ->
case get_resource_type(Source) of
{error, _}=Error ->
Error;
Module ->
try
Module:needs_update(AppDir, Source)
catch
_:_ ->
true
end
Module = get_resource_type(Source),
try
Module:needs_update(AppDir, Source)
catch
_:_ ->
true
end.
get_resource_type({Type, Location}) ->

+ 1
- 1
src/rebar_plugins.erl Переглянути файл

@ -26,7 +26,7 @@ install(State) ->
handle_plugin(Plugin, State) ->
try
{ok, State1} = rebar_prv_install_deps:handle_deps(State, [Plugin]),
Apps = rebar_state:get(State1, all_deps, []),
Apps = rebar_state:all_deps(State1),
ToBuild = lists:dropwhile(fun rebar_app_info:valid/1, Apps),
lists:foreach(fun(AppInfo) ->
AppDir = rebar_app_info:dir(AppInfo),

+ 84
- 60
src/rebar_prv_install_deps.erl Переглянути файл

@ -66,14 +66,14 @@ do(State) ->
Profile = rebar_state:current_profile(State),
ProjectApps = rebar_state:project_apps(State),
try
{ok, State1} = case rebar_state:get(State, locks, []) of
[] ->
handle_deps(State, rebar_state:get(State, {deps, Profile}, []));
Locks ->
handle_deps(State, Locks)
end,
Source = ProjectApps ++ rebar_state:src_apps(State1),
{ok, SrcApps, State1} = case rebar_state:get(State, locks, []) of
[] ->
handle_deps(State, rebar_state:get(State, {deps, Profile}, []));
Locks ->
handle_deps(State, Locks)
end,
Source = ProjectApps ++ SrcApps,
case rebar_digraph:compile_order(Source) of
{ok, Sort} ->
{ok, rebar_state:set(State1, deps_to_build,
@ -106,66 +106,88 @@ handle_deps(State, Deps, Update) ->
%% Split source deps from pkg deps, needed to keep backwards compatibility
DepsDir = rebar_utils:deps_dir(State),
{SrcDeps, PkgDeps} = parse_deps(State, DepsDir, Deps),
State1 = rebar_state:src_deps(rebar_state:pkg_deps(State, PkgDeps),
SrcDeps),
%% Fetch transitive src deps
{State2, _Seen} = update_src_deps(0, State1, Update, sets:new()),
Solved = case rebar_state:pkg_deps(State2) of
[] -> %% No pkg deps
[];
PkgDeps1 ->
%% Find pkg deps needed
S = case rebar_digraph:cull_deps(Graph, PkgDeps1) of
{ok, []} ->
throw({rebar_digraph, no_solution});
{ok, Solution} ->
Solution;
[] ->
throw({rebar_digraph, no_solution})
end,
%% Create app_info record for each pkg dep
[AppInfo || Pkg <- S,
AppInfo <- package_to_app(DepsDir
,Packages
,Pkg),
maybe_fetch(State2, AppInfo, Update, sets:new())]
end,
{State1, SrcApps, PkgDeps1, Seen} =
update_src_deps(0, SrcDeps, PkgDeps, [], State, Update, sets:new()),
{Solved, State2} = case PkgDeps1 of
[] -> %% No pkg deps
{[], State1};
PkgDeps2 ->
%% Find pkg deps needed
S = case rebar_digraph:cull_deps(Graph, PkgDeps2) of
{ok, []} ->
throw({rebar_digraph, no_solution});
{ok, Solution} ->
Solution;
[] ->
throw({rebar_digraph, no_solution})
end,
update_pkg_deps(S, Packages, Update, Seen, State1)
end,
AllDeps = lists:ukeymerge(2
,lists:ukeysort(2, rebar_state:src_apps(State2))
,lists:ukeysort(2, SrcApps)
,lists:ukeysort(2, Solved)),
%% Sort all apps to build order
State3 = rebar_state:set(State2, all_deps, AllDeps),
State4 = rebar_state:set(State3, {all_deps, rebar_state:current_profile(State)}, AllDeps),
{ok, State4}.
State3 = rebar_state:all_deps(State2, AllDeps),
{ok, SrcApps, State3}.
%% ===================================================================
%% Internal functions
%% ===================================================================
update_pkg_deps(Pkgs, Packages, Update, Seen, State) ->
%% Create app_info record for each pkg dep
DepsDir = rebar_utils:deps_dir(State),
{Solved, _, State1}
= lists:foldl(fun(Pkg, {Acc, SeenAcc, StateAcc}) ->
AppInfo = package_to_app(DepsDir
,Packages
,Pkg),
{SeenAcc1, StateAcc1} = maybe_lock(AppInfo, SeenAcc, StateAcc),
case maybe_fetch(StateAcc1, AppInfo, Update, SeenAcc) of
true ->
{[AppInfo | Acc], SeenAcc1, StateAcc1};
false ->
{Acc, SeenAcc1, StateAcc1}
end
end, {[], Seen, State}, Pkgs),
{Solved, State1}.
maybe_lock(AppInfo, Seen, State) ->
Name = rebar_app_info:name(AppInfo),
case sets:is_element(Name, Seen) of
false ->
{sets:add_element(Name, Seen),
rebar_state:lock(State, AppInfo)};
true ->
{sets:add_element(Name, Seen), State}
end.
package_to_app(DepsDir, Packages, {Name, Vsn}) ->
case dict:find({Name, Vsn}, Packages) of
error ->
[];
{error, missing_package};
{ok, P} ->
PkgDeps = proplists:get_value(<<"deps">>, P, []),
Link = proplists:get_value(<<"link">>, P, ""),
{ok, AppInfo} = rebar_app_info:new(Name, Vsn),
AppInfo1 = rebar_app_info:deps(AppInfo, PkgDeps),
AppInfo2 = rebar_app_info:dir(AppInfo1, rebar_utils:deps_dir(DepsDir, Name)),
[rebar_app_info:source(AppInfo2, {pkg, Name, Vsn, Link})]
rebar_app_info:source(AppInfo2, {pkg, Name, Vsn, Link})
end.
-spec update_src_deps(integer(), rebar_state:t(), boolean(), sets:set(binary())) ->
-spec update_src_deps(integer(), list(), list(), list(), rebar_state:t(), boolean(), sets:set(binary())) ->
{rebar_state:t(), [binary()]}.
update_src_deps(Level, State, Update, Seen) ->
SrcDeps = rebar_state:src_deps(State),
case lists:foldl(fun(AppInfo, {SrcDepsAcc, PkgDepsAcc, StateAcc, SeenAcc}) ->
SeenAcc1 = sets:add_element(rebar_app_info:name(AppInfo), SeenAcc),
{SrcDepsAcc1, PkgDepsAcc1, StateAcc1} =
update_src_deps(Level, SrcDeps, PkgDeps, SrcApps, State, Update, Seen) ->
case lists:foldl(fun(AppInfo, {SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc, SeenAcc}) ->
%% If not seen, add to list of locks to write out
{SeenAcc1, StateAcc1} = maybe_lock(AppInfo, SeenAcc, StateAcc),
{SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2} =
case Update of
{true, UpdateName, UpdateLevel} ->
handle_update(AppInfo
@ -173,28 +195,28 @@ update_src_deps(Level, State, Update, Seen) ->
,UpdateLevel
,SrcDepsAcc
,PkgDepsAcc
,SrcAppsAcc
,Level
,StateAcc);
,StateAcc1);
_ ->
maybe_fetch(StateAcc, AppInfo, false, SeenAcc),
handle_dep(AppInfo
,SrcDepsAcc
,PkgDepsAcc
,SrcAppsAcc
,Level
,StateAcc)
,StateAcc1)
end,
{SrcDepsAcc1, PkgDepsAcc1, StateAcc1, SeenAcc1}
end, {[], rebar_state:pkg_deps(State), State, Seen}, SrcDeps) of
{[], NewPkgDeps, State1, Seen1} ->
{rebar_state:pkg_deps(State1, NewPkgDeps), Seen1};
{NewSrcDeps, NewPkgDeps, State1, Seen1} ->
State2 = rebar_state:pkg_deps(State1, NewPkgDeps),
State3 = rebar_state:src_deps(State2, NewSrcDeps),
update_src_deps(Level+1, State3, Update, Seen1)
{SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2, SeenAcc1}
end, {[], PkgDeps, SrcApps, State, Seen}, SrcDeps) of
{[], NewPkgDeps, NewSrcApps, State1, Seen1} ->
{State1, NewSrcApps, NewPkgDeps, Seen1};
{NewSrcDeps, NewPkgDeps, NewSrcApps, State1, Seen1} ->
update_src_deps(Level+1, NewSrcDeps, NewPkgDeps, NewSrcApps, State1, Update, Seen1)
end.
handle_update(AppInfo, UpdateName, UpdateLevel, SrcDeps, PkgDeps, Level, State) ->
handle_update(AppInfo, UpdateName, UpdateLevel, SrcDeps, PkgDeps, SrcApps, Level, State) ->
Name = rebar_app_info:name(AppInfo),
Locks = rebar_state:get(State, locks, []),
{_, _, _, DepLevel} = lists:keyfind(Name, 1, Locks),
@ -206,24 +228,26 @@ handle_update(AppInfo, UpdateName, UpdateLevel, SrcDeps, PkgDeps, Level, State)
handle_dep(AppInfo
,SrcDeps
,PkgDeps
,SrcApps
,Level
,State);
false ->
{SrcDeps, PkgDeps, State}
{SrcDeps, PkgDeps, SrcApps, State}
end;
false ->
{SrcDeps, PkgDeps, State}
{SrcDeps, PkgDeps, SrcApps, State}
end.
handle_dep(AppInfo, SrcDeps, PkgDeps, Level, State) ->
handle_dep(AppInfo, SrcDeps, PkgDeps, SrcApps, Level, State) ->
DepsDir = rebar_utils:deps_dir(State),
{AppInfo1, NewSrcDeps, NewPkgDeps} =
handle_dep(State, DepsDir, AppInfo),
AppInfo2 = rebar_app_info:dep_level(AppInfo1, Level),
{NewSrcDeps ++ SrcDeps
,NewPkgDeps++PkgDeps
,rebar_state:src_apps(State, AppInfo2)}.
,[AppInfo2 | SrcApps]
,State}.
-spec handle_dep(rebar_state:t(), file:filename_all(), rebar_app_info:t()) ->
{rebar_app_info:t(), [rebar_app_info:t()], [pkg_dep()]}.

+ 5
- 11
src/rebar_prv_lock.erl Переглянути файл

@ -31,23 +31,17 @@ init(State) ->
do(State) ->
case rebar_state:get(State, locks, []) of
[] ->
AllDeps = rebar_state:get(State, {all_deps, default}, []),
AllDeps = rebar_state:lock(State),
Locks = lists:map(fun(Dep) ->
Dir = rebar_app_info:dir(Dep),
Source = rebar_app_info:source(Dep),
%% If source is tuple it is a source dep
%% e.g. {git, "git://github.com/ninenines/cowboy.git", "master"}
case Source of
Source when is_tuple(Source) ->
{rebar_app_info:name(Dep)
,rebar_app_info:original_vsn(Dep)
,rebar_fetch:lock_source(Dir, Source)
,rebar_app_info:dep_level(Dep)};
_Source ->
{rebar_app_info:name(Dep)
,rebar_app_info:original_vsn(Dep)}
end
{rebar_app_info:name(Dep)
,rebar_app_info:original_vsn(Dep)
,rebar_fetch:lock_source(Dir, Source)
,rebar_app_info:dep_level(Dep)}
end, AllDeps),
Dir = rebar_state:dir(State),
file:write_file(filename:join(Dir, "rebar.lock"), io_lib:format("~p.~n", [Locks])),

+ 19
- 36
src/rebar_state.erl Переглянути файл

@ -3,6 +3,9 @@
-export([new/0, new/1, new/2, new/3,
get/2, get/3, set/3,
lock/1,
lock/2,
current_profile/1,
current_profile/2,
@ -15,11 +18,9 @@
create_logic_providers/2,
project_apps/1, project_apps/2,
all_deps/1, all_deps/2,
deps_names/1,
pkg_deps/1, pkg_deps/2,
src_deps/1, src_deps/2,
src_apps/1, src_apps/2,
prepend_hook/3, append_hook/3, hooks/2,
providers/1, providers/2, add_provider/2]).
@ -29,15 +30,14 @@
-record(state_t, {dir :: file:name(),
opts = dict:new() :: rebar_dict(),
lock = [],
current_profile = default :: atom(),
command_args = [],
command_parsed_args = [],
src_deps = [],
src_apps = [],
pkg_deps = [] :: [rebar_packages:package()],
project_apps = [],
project_apps = [] :: [rebar_app_into:t()],
all_deps = [] :: [rebar_app_into:t()],
providers = []}).
@ -99,6 +99,12 @@ current_profile(#state_t{current_profile=Profile}) ->
current_profile(State, Profile) ->
State#state_t{current_profile=Profile}.
lock(#state_t{lock=Lock}) ->
Lock.
lock(State=#state_t{lock=Lock}, App) ->
State#state_t{lock=[App | Lock]}.
command_args(#state_t{command_args=CmdArgs}) ->
CmdArgs.
@ -151,35 +157,6 @@ deps_names(State) ->
Deps = rebar_state:get(State, deps, []),
deps_names(Deps).
-spec pkg_deps(t()) -> [rebar_packages:package()].
pkg_deps(#state_t{pkg_deps=PkgDeps}) ->
PkgDeps.
pkg_deps(State=#state_t{pkg_deps=PkgDeps}, NewPkgDeps) when is_list(PkgDeps) ->
State#state_t{pkg_deps=NewPkgDeps};
pkg_deps(State=#state_t{pkg_deps=PkgDeps}, PkgDep) ->
State#state_t{pkg_deps=[PkgDep | PkgDeps]}.
src_deps(#state_t{src_deps=SrcDeps}) ->
SrcDeps.
src_deps(State=#state_t{src_deps=SrcDeps}, NewSrcDeps) when is_list(SrcDeps) ->
State#state_t{src_deps=NewSrcDeps};
src_deps(State=#state_t{src_deps=SrcDeps}, SrcDep) ->
Name = rebar_app_info:name(SrcDep),
NewSrcDeps = lists:keystore(Name, 2, SrcDeps, SrcDep),
State#state_t{src_deps=NewSrcDeps}.
src_apps(#state_t{src_apps=SrcApps}) ->
SrcApps.
src_apps(State=#state_t{src_apps=_SrcApps}, NewSrcApps) when is_list(NewSrcApps) ->
State#state_t{src_apps=NewSrcApps};
src_apps(State=#state_t{src_apps=SrcApps}, NewSrcApp) ->
Name = rebar_app_info:name(NewSrcApp),
NewSrcApps = lists:keystore(Name, 2, SrcApps, NewSrcApp),
State#state_t{src_apps=NewSrcApps}.
project_apps(#state_t{project_apps=Apps}) ->
Apps.
@ -188,6 +165,12 @@ project_apps(State=#state_t{}, NewApps) when is_list(NewApps) ->
project_apps(State=#state_t{project_apps=Apps}, App) ->
State#state_t{project_apps=lists:keystore(rebar_app_info:name(App), 2, Apps, App)}.
all_deps(#state_t{all_deps=Apps}) ->
Apps.
all_deps(State=#state_t{}, NewApps) ->
State#state_t{all_deps=NewApps}.
providers(#state_t{providers=Providers}) ->
Providers.

Завантаження…
Відмінити
Зберегти