3636 % provider
3737 do /1 ,
3838 format_error /1 ,
39+ init /2 ,
40+ % rebar_resource_v2 callbacks
41+ download /4 ,
42+ lock /2 ,
43+ make_vsn /2 ,
44+ needs_update /2 ,
45+ % pre-rebar3 3.7.0 rebar_resource callbacks
3946 init /1 ,
40- % rebar_resource
4147 download /3 ,
42- lock /2 ,
43- make_vsn /1 ,
44- needs_update /2
48+ make_vsn /1
4549]).
4650
4751% For development only - you *really* don't want this defined!
194198% download/3 is NOT called first if the dependency is already present, and
195199% it's the only resource call that gets to see the rebar state.
196200%
201+ % Note: This arity is the pre-rebar3 3.7.0 format of this function.
202+ %
197203init (State ) ->
198204 # mod_data {} = absorb_state (State ),
199205 {'ok' , rebar_state :add_resource (State , {? RTYPE , ? MODULE })}.
200206
207+ -spec init (Type :: rsrc_type (),
208+ State :: rebar_state ()) -> {'ok' , rebar_state ()}.
209+ %
210+ % Installs the resource handler, the provider itself does nothing.
211+ %
212+ % This gets called repeatedly, for each profile, and in each case we want
213+ % to prime the process environment with any info we may need later, as
214+ % download/4 is NOT called first if the dependency is already present, and
215+ % it's the only resource call that gets to see the rebar state.
216+ %
217+ % Note: This arity is the rebar_resource_v2 format of this function.
218+ %
219+ init (Type , State ) ->
220+ # mod_data {} = absorb_state (State ),
221+ {'ok' , rebar_resource_v2 :new (Type , ? MODULE , State )}.
222+
201223-spec do (State :: rebar_state :t ()) -> {'ok' , rebar_state ()}.
202224%
203225% Fulfills the `provider' contract, does nothing ... for now.
@@ -225,14 +247,18 @@ format_error(Error) ->
225247% % Resource API
226248% % ===================================================================
227249
228- -spec download (
229- Dest :: rsrc_dir (), From :: this_spec (), State :: rebar_state ())
230- -> {'ok' , term ()} | rebar_err ().
250+ -spec download (Dest :: rsrc_dir (),
251+ From :: this_spec (),
252+ State :: rebar_state ())
253+ -> {'ok' , term ()} | rebar_err ().
231254%
232255% Download the specified resource using its underlying handler.
233256%
234- download (Dest , {? RTYPE , Loc ,
235- # mod_ref {res = Res , ref = Ref , opt = Opts }}, State ) ->
257+ % Note: This arity is the pre-rebar3 3.7.0 format of this function.
258+ %
259+ download (Dest ,
260+ {? RTYPE , Loc , # mod_ref {res = Res , ref = Ref , opt = Opts }},
261+ State ) ->
236262 download (Dest , {? RTYPE , {Res , Loc , Ref }, Opts }, State );
237263
238264download (Dest , {? RTYPE , Spec }, State ) ->
@@ -254,13 +280,60 @@ download(Dest, {?RTYPE, Spec, Opts}, State) ->
254280 Err
255281 end .
256282
257- -spec lock (Path :: rsrc_dir (), Spec :: this_spec ())
258- -> rebar_lock () | no_return ().
283+ -spec download (Dest :: rsrc_dir (),
284+ AppInfo :: rebar_app_info :t (),
285+ ResourceState :: term (),
286+ State :: rebar_state ())
287+ -> {'ok' , term ()} | rebar_err ().
288+ %
289+ % Download the specified resource using its underlying handler.
290+ %
291+ % Note: This arity is the rebar_resource_v2 format of this function.
292+ %
293+ download (Dest , AppInfo0 , ResourceState , RebarState ) ->
294+ {Spec , Opts } = case rebar_app_info :source (AppInfo0 ) of
295+ {? RTYPE , Loc0 , # mod_ref {res = Res0 , ref = Ref , opt = Opts0 }} ->
296+ {{Res0 , Loc0 , Ref }, Opts0 };
297+ {? RTYPE , S , O } ->
298+ {S , O };
299+ {? RTYPE , S } ->
300+ {S , []}
301+ end ,
302+ {Res , Loc } = parse_ext_spec (Spec ),
303+ # mod_dep {name = Name } = lookup_loc (mod_data (), Loc ),
304+ # mod_res {mod = Mod } = lookup_res (mod_data (), Res ),
305+ AppInfo = rebar_app_info :source (AppInfo0 , Spec ),
306+ case Mod :download (Dest , AppInfo , ResourceState , RebarState ) of
307+ ok ->
308+ case lists :keytake (vsn , 1 , Opts ) of
309+ false ->
310+ % because download has not put the downloaded app into
311+ % its final location, configure the app dir to be the
312+ % Dest provided.
313+ TmpAppInfo = rebar_app_info :dir (AppInfo , Dest ),
314+ {plain , Vsn } = Mod :make_vsn (TmpAppInfo , []),
315+ ensure_app (Dest , Mod , Name , [{vsn , Vsn } |Opts ], ok );
316+ {value , _ , _ } ->
317+ ensure_app (Dest , Mod , Name , Opts , ok )
318+ end ;
319+ Err -> Err
320+ end .
321+
322+ -spec lock (Path :: rsrc_dir (),
323+ Spec :: this_spec ())
324+ -> rebar_lock () | no_return ();
325+ (AppInfo :: rebar_app_info :t (),
326+ ResourceState :: term ())
327+ -> rebar_lock () | no_return ().
259328%
260329% Pass through to the underlying resource handler.
261330% Note that the callback doesn't allow an error tuple to be returned, so an
262331% exception is our only option if we can't look up the mapping.
263332%
333+ % Note: this function is common to the pre-rebar3 3.7.0 and rebar_resource_v2
334+ % formats, and as such has heads for each.
335+ %
336+ % % pre-rebar3 3.7.0 format
264337lock (Path , {? RTYPE , Loc , # mod_ref {res = Res , ref = Prev } = Rec }) ->
265338 # mod_res {mod = Mod } = lookup_res (mod_data (), Res ),
266339 {Res , Loc , Ref } = Mod :lock (Path , {Res , Loc , Prev }),
@@ -273,15 +346,35 @@ lock(Path, {?RTYPE, Spec, Opts}) ->
273346 {Res , _ } = parse_ext_spec (Spec ),
274347 # mod_res {mod = Mod } = lookup_res (mod_data (), Res ),
275348 {Res , Loc , Ref } = Mod :lock (Path , Spec ),
349+ {? RTYPE , Loc , # mod_ref {res = Res , ref = Ref , opt = Opts }};
350+ % % rebar_resource_v2 format
351+ lock (AppInfo , _ResourceState ) ->
352+ {Spec , Opts } = case rebar_app_info :source (AppInfo ) of
353+ {? RTYPE , Loc0 , # mod_ref {res = Res0 , ref = Ref0 , opt = Opts0 }} ->
354+ {{Res0 , Loc0 , Ref0 }, Opts0 };
355+ {? RTYPE , S , O } -> {S , O };
356+ {? RTYPE , S } -> {S , []}
357+ end ,
358+ {Res , _Loc } = parse_ext_spec (Spec ),
359+ # mod_res {mod = Mod } = lookup_res (mod_data (), Res ),
360+ {Res , Loc , Ref } = Mod :lock (rebar_app_info :source (AppInfo , Spec ), []),
276361 {? RTYPE , Loc , # mod_ref {res = Res , ref = Ref , opt = Opts }}.
277362
278- -spec needs_update (Path :: rsrc_dir (), Spec :: this_spec ())
279- -> boolean () | no_return ().
363+ -spec needs_update (Path :: rsrc_dir (),
364+ SpecOrResourceState :: this_spec ())
365+ -> boolean () | no_return ();
366+ (AppInfo :: rebar_app_info :t (),
367+ State :: rebar_state ())
368+ -> boolean () | no_return ().
280369%
281370% Pass through to the underlying resource handler.
282371% Note that the callback doesn't allow an error tuple to be returned, so an
283372% exception is our only option if we can't look up the mapping.
284373%
374+ % Note: this function is common to the pre-rebar3 3.7.0 and rebar_resource_v2
375+ % formats, and as such has heads for each.
376+ %
377+ % % pre-rebar3 3.7.0 format
285378needs_update (Path , {? RTYPE , Loc , # mod_ref {res = Res , ref = Ref }}) ->
286379 # mod_res {mod = Mod } = lookup_res (mod_data (), Res ),
287380 Mod :needs_update (Path , {Res , Loc , Ref });
@@ -292,20 +385,55 @@ needs_update(Path, {?RTYPE, Spec, _}) ->
292385needs_update (Path , {? RTYPE , Spec }) ->
293386 {Res , _ } = parse_ext_spec (Spec ),
294387 # mod_res {mod = Mod } = lookup_res (mod_data (), Res ),
295- Mod :needs_update (Path , Spec ).
388+ Mod :needs_update (Path , Spec );
389+ % % rebar_resource_v2 format
390+ needs_update (AppInfo , State ) ->
391+ {Mod , SourceSpec } = case rebar_app_info :source (AppInfo ) of
392+ {? RTYPE , Loc , # mod_ref {res = Res , ref = Ref }} ->
393+ # mod_res {mod = M } = lookup_res (mod_data (), Res ),
394+ {M , {Res , Loc , Ref }};
395+ {? RTYPE , Spec , _ } ->
396+ {Res , _ } = parse_ext_spec (Spec ),
397+ # mod_res {mod = M } = lookup_res (mod_data (), Res ),
398+ {M , Spec };
399+ {? RTYPE , Spec } ->
400+ {Res , _ } = parse_ext_spec (Spec ),
401+ # mod_res {mod = M } = lookup_res (mod_data (), Res ),
402+ {M , Spec }
403+ end ,
404+ Mod :needs_update (rebar_app_info :source (AppInfo , SourceSpec ), State ).
296405
297406-spec make_vsn (Path :: rsrc_dir ())
298407 -> rebar_vsn () | {'error' , string ()} | no_return ().
299408%
300409% Pass through to the underlying resource handler.
301410% The weird error tuple spec comes from the rebar_resource behavior.
411+ % Note: This arity is the pre-rebar3 3.7.0 format of this function.
302412%
303413make_vsn (Path ) ->
304414 Data = mod_data (),
305415 # mod_dep {res = Res } = lookup_dep (Data , path_name (Path )),
306416 # mod_res {mod = Mod } = lookup_res (Data , Res ),
307417 Mod :make_vsn (Path ).
308418
419+ -spec make_vsn (Path :: rsrc_dir (),
420+ State :: rebar_state ())
421+ -> rebar_vsn () | {'error' , string ()} | no_return ().
422+ %
423+ % Pass through to the underlying resource handler.
424+ % The weird error tuple spec comes from the rebar_resource behavior.
425+ % Note: This arity is the rebar_resource_v2 format of this function.
426+ %
427+ make_vsn (AppInfo0 , _ResourceState ) ->
428+ Spec = case rebar_app_info :source (AppInfo0 ) of
429+ {? RTYPE , Loc0 , # mod_ref {res = Res0 , ref = Ref }} -> {Res0 , Loc0 , Ref };
430+ {? RTYPE , S , _ } -> S ;
431+ {? RTYPE , S } -> S
432+ end ,
433+ {Res , _Loc } = parse_ext_spec (Spec ),
434+ # mod_res {mod = Mod } = lookup_res (mod_data (), Res ),
435+ Mod :make_vsn (rebar_app_info :source (AppInfo0 , Spec ), []).
436+
309437% % ===================================================================
310438% % Internal
311439% % ===================================================================
@@ -348,16 +476,21 @@ format_error(Mod, Func, Class, Data) ->
348476absorb_state (State ) ->
349477 Data1 = mod_data (),
350478 Data2 = absorb_resources (Data1 , rebar_state :resources (State )),
351- Data3 = absorb_deps (Data2 , rebar_state :get (State , 'deps' , [] )),
352- Data4 = absorb_app_infos (Data3 , rebar_state :lock (State )),
479+ Data3 = absorb_app_infos (Data2 , rebar_state :lock (State )),
480+ Data4 = absorb_deps (Data3 , rebar_state :get (State , 'deps' , [] )),
353481% Data5 = absorb_profiles(Data4, rebar_state:current_profiles(State), State),
354482 mod_data (dump_mod_data (Data4 )).
355483
356484-spec absorb_app_infos (Data :: mod_data (), AppInfos :: [tuple ()])
357485 -> mod_data () | no_return ().
358486absorb_app_infos (Data , [AppInfo | AppInfos ]) ->
487+ % absorb deps from app_info to ensure that all deps are absorbed
488+ % see comments in https://github.com/alertlogic/rebar_raw_resource/pull/1
489+ % for further discussion.
490+ AppInfoDeps = rebar_app_info :get (AppInfo , deps , []),
359491 absorb_app_infos (
360- absorb_dep (Data ,
492+ absorb_dep (
493+ absorb_deps (Data , AppInfoDeps ),
361494 rebar_app_info :name (AppInfo ), rebar_app_info :source (AppInfo )),
362495 AppInfos );
363496absorb_app_infos (Data , []) ->
@@ -390,14 +523,14 @@ absorb_profiles(Data, [], _) ->
390523%
391524% Allow for whatever may come through to handle future extensions.
392525%
393- % rebar v2 resource
526+ % rebar_resource_v2 format
394527absorb_resources (Data , [Res | Resources ]) when ? is_rec_type (Res , resource , 3 ) ->
395528 absorb_resources (
396529 map_res (Data , # mod_res {
397530 res = term_to_atom (erlang :element (2 , Res )),
398531 mod = erlang :element (3 , Res )}),
399532 Resources );
400- % old style rebar resource
533+ % pre-rebar3 3.7.0 format
401534absorb_resources (Data , [Res | Resources ]) when ? is_min_tuple (Res , 2 ) ->
402535 absorb_resources (
403536 map_res (Data , # mod_res {
@@ -480,9 +613,9 @@ ensure_app(Path, Mod, Name, Opts, Result) ->
480613 " {applications, [kernel, stdlib]}\n "
481614 " ]}.\n " ,
482615 [? MODULE , Name , Desc , Vsn ]),
483- case filelib :ensure_dir (BApp ) of
616+ case filelib :ensure_dir (SApp ) of
484617 'ok' ->
485- case file :write_file (BApp , Data ) of
618+ case file :write_file (SApp , Data ) of
486619 'ok' ->
487620 Result ;
488621 Err ->
0 commit comments