1-module(rebar_prv_unlock). 2 3-behaviour(provider). 4 5-export([init/1, 6 do/1, 7 format_error/1]). 8 9-include("rebar.hrl"). 10-include_lib("providers/include/providers.hrl"). 11 12-define(PROVIDER, unlock). 13-define(DEPS, []). 14 15%% =================================================================== 16%% Public API 17%% =================================================================== 18 19-spec init(rebar_state:t()) -> {ok, rebar_state:t()}. 20init(State) -> 21 State1 = rebar_state:add_provider( 22 State, 23 providers:create([{name, ?PROVIDER}, 24 {module, ?MODULE}, 25 {bare, true}, 26 {deps, ?DEPS}, 27 {example, ""}, 28 {short_desc, "Unlock dependencies."}, 29 {desc, "Unlock project dependencies. Mentioning no application " 30 "will unlock all dependencies. To unlock specific dependencies, " 31 "their name can be listed in the command."}, 32 {opts, [ 33 {package, undefined, undefined, string, 34 "List of packages to unlock. If not specified, all dependencies are unlocked."} 35 ]} 36 ]) 37 ), 38 {ok, State1}. 39 40do(State) -> 41 Dir = rebar_state:dir(State), 42 LockFile = filename:join(Dir, ?LOCK_FILE), 43 case file:consult(LockFile) of 44 {error, enoent} -> 45 %% Our work is done. 46 {ok, State}; 47 {error, Reason} -> 48 ?PRV_ERROR({file,Reason}); 49 {ok, _} -> 50 Locks = rebar_config:consult_lock_file(LockFile), 51 {ok, NewLocks} = handle_unlocks(State, Locks, LockFile), 52 {ok, rebar_state:set(State, {locks, default}, NewLocks)} 53 end. 54 55-spec format_error(any()) -> iolist(). 56format_error({file, Reason}) -> 57 io_lib:format("Lock file editing failed for reason ~p", [Reason]); 58format_error(unknown_lock_format) -> 59 "Lock file format unknown"; 60format_error(Reason) -> 61 io_lib:format("~p", [Reason]). 62 63handle_unlocks(State, Locks, LockFile) -> 64 {Args, _} = rebar_state:command_parsed_args(State), 65 Names = parse_names(rebar_utils:to_binary(proplists:get_value(package, Args, <<"">>))), 66 case [Lock || Lock = {Name, _, _} <- Locks, not lists:member(Name, Names)] of 67 [] -> 68 file:delete(LockFile), 69 {ok, []}; 70 _ when Names =:= [] -> % implicitly all locks 71 file:delete(LockFile), 72 {ok, []}; 73 NewLocks -> 74 rebar_config:write_lock_file(LockFile, NewLocks), 75 {ok, NewLocks} 76 end. 77 78parse_names(Bin) -> 79 case lists:usort(re:split(Bin, <<" *, *">>, [trim, unicode])) of 80 [<<"">>] -> []; % nothing submitted 81 Other -> Other 82 end. 83