diff --git a/priv/shell-completion/bash/rebar b/priv/shell-completion/bash/rebar index 237255c..ead10ff 100644 --- a/priv/shell-completion/bash/rebar +++ b/priv/shell-completion/bash/rebar @@ -10,7 +10,7 @@ _rebar() lopts=" --help --commands --verbose --force --jobs= --version" cmdsnvars="build-plt check-plt check-deps clean compile \ create create-app create-node ct dialyze doc delete-deps eunit \ - get-deps generate help list-templates version xref \ + get-deps generate help list-templates update-deps version xref \ case= debug_info=1 force=1 jobs= suite= verbose=1 appid= \ skip_deps=1 template= template_dir=" diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 3c64f8d..e8b4e57 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -223,6 +223,7 @@ doc Generate Erlang program documentation check-deps Display to be fetched dependencies get-deps Fetch dependencies +update-deps Update fetched dependencies delete-deps Delete fetched dependencies generate [dump_spec=0/1] Build release with reltool diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl index 0852b01..a86b83c 100644 --- a/src/rebar_deps.erl +++ b/src/rebar_deps.erl @@ -33,6 +33,7 @@ compile/2, 'check-deps'/2, 'get-deps'/2, + 'update-deps'/2, 'delete-deps'/2]). @@ -54,7 +55,7 @@ preprocess(Config, _) -> %% Get the list of deps for the current working directory and identify those %% deps that are available/present. Deps = rebar_config:get_local(Config, deps, []), - {AvailableDeps, MissingDeps} = find_deps(Deps), + {AvailableDeps, MissingDeps} = find_deps(find, Deps), ?DEBUG("Available deps: ~p\n", [AvailableDeps]), ?DEBUG("Missing deps : ~p\n", [MissingDeps]), @@ -93,7 +94,7 @@ compile(Config, AppFile) -> 'check-deps'(Config, _) -> %% Get the list of immediate (i.e. non-transitive) deps that are missing Deps = rebar_config:get_local(Config, deps, []), - case find_deps(Deps) of + case find_deps(find, Deps) of {_, []} -> %% No missing deps ok; @@ -108,26 +109,31 @@ compile(Config, AppFile) -> 'get-deps'(Config, _) -> %% Determine what deps are available and missing Deps = rebar_config:get_local(Config, deps, []), - {AvailableDeps, MissingDeps} = find_deps(Deps), + {_AvailableDeps, MissingDeps} = find_deps(find, Deps), %% For each missing dep with a specified source, try to pull it. - PulledDeps0 = [use_source(D) || D <- MissingDeps, D#dep.source /= undefined], - - %% For each available dep try to update the source to the specified - %% version. - PulledDeps1 = [update_source(D) || D <- AvailableDeps, - D#dep.source /= undefined], + PulledDeps = [use_source(D) || D <- MissingDeps, D#dep.source /= undefined], %% Add each pulled dep to our list of dirs for post-processing. This yields %% the necessary transitivity of the deps - erlang:put(?MODULE, [D#dep.dir || D <- PulledDeps0 ++ PulledDeps1]), + erlang:put(?MODULE, [D#dep.dir || D <- PulledDeps]), + ok. + +'update-deps'(Config, _) -> + %% Determine what deps are available and missing + Deps = rebar_config:get_local(Config, deps, []), + UpdatedDeps = [update_source(D) || D <- find_deps(read, Deps), + D#dep.source /= undefined], + %% Add each updated dep to our list of dirs for post-processing. This yields + %% the necessary transitivity of the deps + erlang:put(?MODULE, [D#dep.dir || D <- UpdatedDeps]), ok. 'delete-deps'(Config, _) -> %% Delete all the available deps in our deps/ directory, if any DepsDir = get_deps_dir(), Deps = rebar_config:get_local(Config, deps, []), - {AvailableDeps, _} = find_deps(Deps), + {AvailableDeps, _} = find_deps(find, Deps), _ = [delete_dep(D) || D <- AvailableDeps, lists:prefix(DepsDir, D#dep.dir) == true], ok. @@ -163,35 +169,48 @@ update_deps_code_path([Dep | Rest]) -> end, update_deps_code_path(Rest). -find_deps(Deps) -> - find_deps(Deps, {[], []}). -find_deps([], {Avail, Missing}) -> +find_deps(find=Mode, Deps) -> + find_deps(Mode, Deps, {[], []}); +find_deps(read=Mode, Deps) -> + find_deps(Mode, Deps, []). + +find_deps(find, [], {Avail, Missing}) -> {lists:reverse(Avail), lists:reverse(Missing)}; -find_deps([App | Rest], Acc) when is_atom(App) -> - find_deps([{App, ".*", undefined} | Rest], Acc); -find_deps([{App, VsnRegex} | Rest], Acc) when is_atom(App) -> - find_deps([{App, VsnRegex, undefined} | Rest], Acc); -find_deps([{App, VsnRegex, Source} | Rest], {Avail, Missing}) -> +find_deps(read, [], Deps) -> + lists:reverse(Deps); +find_deps(Mode, [App | Rest], Acc) when is_atom(App) -> + find_deps(Mode, [{App, ".*", undefined} | Rest], Acc); +find_deps(Mode, [{App, VsnRegex} | Rest], Acc) when is_atom(App) -> + find_deps(Mode, [{App, VsnRegex, undefined} | Rest], Acc); +find_deps(Mode, [{App, VsnRegex, Source} | Rest], Acc) -> Dep = #dep { app = App, vsn_regex = VsnRegex, source = Source }, case is_app_available(App, VsnRegex) of {true, AppDir} -> - find_deps(Rest, {[Dep#dep { dir = AppDir } | Avail], Missing}); + find_deps(Mode, Rest, acc_deps(Mode, avail, Dep, AppDir, Acc)); {false, _} -> AppDir = filename:join(get_deps_dir(), Dep#dep.app), case is_app_available(App, VsnRegex, AppDir) of {true, AppDir} -> - find_deps(Rest, {[Dep#dep { dir = AppDir } | Avail], Missing}); + find_deps(Mode, Rest, + acc_deps(Mode, avail, Dep, AppDir, Acc)); {false, _} -> - find_deps(Rest, {Avail, [Dep#dep { dir = AppDir } | Missing]}) + find_deps(Mode, Rest, + acc_deps(Mode, missing, Dep, AppDir, Acc)) end end; -find_deps([Other | _Rest], _Acc) -> +find_deps(_Mode, [Other | _Rest], _Acc) -> ?ABORT("Invalid dependency specification ~p in ~s\n", [Other, rebar_utils:get_cwd()]). +acc_deps(find, avail, Dep, AppDir, {Avail, Missing}) -> + {[Dep#dep { dir = AppDir } | Avail], Missing}; +acc_deps(find, missing, Dep, AppDir, {Avail, Missing}) -> + {Avail, [Dep#dep { dir = AppDir } | Missing]}; +acc_deps(read, _, Dep, AppDir, Acc) -> + [Dep#dep { dir = AppDir } | Acc]. delete_dep(D) -> case filelib:is_dir(D#dep.dir) of