-module(rebar_prv_unlock). -behaviour(provider). -export([init/1, do/1, format_error/1]). -include("rebar.hrl"). -include_lib("providers/include/providers.hrl"). -define(PROVIDER, unlock). -define(DEPS, []). %% =================================================================== %% Public API %% =================================================================== -spec init(rebar_state:t()) -> {ok, rebar_state:t()}. init(State) -> State1 = rebar_state:add_provider( State, providers:create([{name, ?PROVIDER}, {module, ?MODULE}, {bare, true}, {deps, ?DEPS}, {example, ""}, {short_desc, "Unlock dependencies."}, {desc, "Unlock project dependencies. Mentioning no application " "will unlock all dependencies. To unlock specific dependencies, " "their name can be listed in the command."}, {opts, [ {package, undefined, undefined, string, "List of packages to unlock. If not specified, all dependencies are unlocked."} ]} ]) ), {ok, State1}. do(State) -> Dir = rebar_state:dir(State), LockFile = filename:join(Dir, ?LOCK_FILE), case file:consult(LockFile) of {error, enoent} -> %% Our work is done. {ok, State}; {error, Reason} -> ?PRV_ERROR({file,Reason}); {ok, _} -> Locks = rebar_config:consult_lock_file(LockFile), {ok, NewLocks} = handle_unlocks(State, Locks, LockFile), {ok, rebar_state:set(State, {locks, default}, NewLocks)} end. -spec format_error(any()) -> iolist(). format_error({file, Reason}) -> io_lib:format("Lock file editing failed for reason ~p", [Reason]); format_error(unknown_lock_format) -> "Lock file format unknown"; format_error(Reason) -> io_lib:format("~p", [Reason]). handle_unlocks(State, Locks, LockFile) -> {Args, _} = rebar_state:command_parsed_args(State), Names = parse_names(rebar_utils:to_binary(proplists:get_value(package, Args, <<"">>))), case [Lock || Lock = {Name, _, _} <- Locks, not lists:member(Name, Names)] of [] -> file:delete(LockFile), {ok, []}; _ when Names =:= [] -> % implicitly all locks file:delete(LockFile), {ok, []}; NewLocks -> rebar_config:write_lock_file(LockFile, NewLocks), {ok, NewLocks} end. parse_names(Bin) -> case lists:usort(re:split(Bin, <<" *, *">>, [trim, unicode])) of [<<"">>] -> []; % nothing submitted Other -> Other end.