@@ -273,7 +273,25 @@ create_release(State0, Release0, OutputDir) ->
273273 ok = rlx_file_utils :write_term (StartCleanFile , StartCleanMeta ),
274274 ok = rlx_file_utils :write_term (NoDotErlFile , NoDotErlMeta ),
275275 write_bin_file (State1 , Release1 , OutputDir , ReleaseDir ),
276- {ok , State1 }.
276+ % check for existing start script extensions and append
277+ % the overlays necessary for them to be copied over to the
278+ % release
279+ State2 = apply_extension_overlays (
280+ rlx_state :extended_start_script_extensions (State1 ), State1 ),
281+ {ok , State2 }.
282+
283+ apply_extension_overlays ([], State ) -> State ;
284+ apply_extension_overlays ([{Name , ExtensionSrc } | Rest ], State ) ->
285+ ExtensionTarget = extension_default_target (ExtensionSrc ),
286+ apply_extension_overlays ([{Name , ExtensionSrc , ExtensionTarget } | Rest ], State );
287+ apply_extension_overlays ([{Name , ExtensionSrc , _ExtensionDescription } | Rest ], State ) ->
288+ ExtensionTarget = extension_default_target (ExtensionSrc ),
289+ apply_extension_overlays ([{Name , ExtensionSrc , ExtensionTarget , _ExtensionDescription } | Rest ], State );
290+ apply_extension_overlays ([{_ , ExtensionSrc , ExtensionTarget , _ } | Rest ], State0 ) ->
291+ State1 = rlx_state :overlay (State0 ,
292+ [{copy , ExtensionSrc , ExtensionTarget } | rlx_state :overlay (State0 )]),
293+ % create the overlay instruction that will copy the extension script to it's release location
294+ apply_extension_overlays (Rest , State1 ).
277295
278296write_bin_file (State , Release , OutputDir , RelDir ) ->
279297 BinDir = filename :join ([OutputDir , " bin" ]),
@@ -317,7 +335,7 @@ write_start_scripts_for(Type, Release, OutputDir, State) ->
317335 % % extended start script needs nodetool so it's
318336 % % always included
319337 include_nodetool (BinDir ),
320- Hooks = expand_hooks (BinDir ,
338+ Hooks = expand_hooks (OutputDir ,
321339 rlx_state :extended_start_script_hooks (State ),
322340 State ),
323341 Extensions = rlx_state :extended_start_script_extensions (State ),
@@ -361,20 +379,20 @@ write_start_script(BaseName, Type, StartFile) ->
361379 ok = file :write_file (RelStartFile , StartFile ),
362380 ok = file :change_mode (RelStartFile , 8#755 ).
363381
364- expand_hooks (_Bindir , [], _State ) -> [];
365- expand_hooks (BinDir , Hooks , _State ) ->
366- expand_hooks (BinDir , Hooks , [], _State ).
382+ expand_hooks (_OutputDir , [], _State ) -> [];
383+ expand_hooks (OutputDir , Hooks , _State ) ->
384+ expand_hooks (OutputDir , Hooks , [], _State ).
367385
368- expand_hooks (_BinDir , [], Acc , _State ) -> Acc ;
369- expand_hooks (BinDir , [{Phase , Hooks0 } | Rest ], Acc , State ) ->
386+ expand_hooks (_OutputDir , [], Acc , _State ) -> Acc ;
387+ expand_hooks (OutputDir , [{Phase , Hooks0 } | Rest ], Acc , State ) ->
370388 % % filter and expand hooks to their respective shell scripts
371389 Hooks =
372390 lists :foldl (
373391 fun (Hook , Acc0 ) ->
374392 case validate_hook (Phase , Hook ) of
375393 true ->
376- % % all hooks are relative to the bin dir
377- HookScriptFilename = filename :join ([BinDir ,
394+ % % all hooks are relative to the release root dir
395+ HookScriptFilename = filename :join ([OutputDir ,
378396 hook_filename (Hook )]),
379397 % % write the hook script file to it's proper location
380398 ok = render_hook (hook_template (Hook ), HookScriptFilename , State ),
@@ -386,7 +404,7 @@ expand_hooks(BinDir, [{Phase, Hooks0} | Rest], Acc, State) ->
386404 Acc0
387405 end
388406 end , [], Hooks0 ),
389- expand_hooks (BinDir , Rest , Acc ++ [{Phase , Hooks }], State ).
407+ expand_hooks (OutputDir , Rest , Acc ++ [{Phase , Hooks }], State ).
390408
391409% % the pid script hook is only allowed in the
392410% % post_start phase
@@ -399,43 +417,48 @@ validate_hook(post_start, wait_for_vm_start) -> true;
399417validate_hook (post_start , {wait_for_process , _ }) -> true ;
400418% % custom hooks are allowed in all phases
401419validate_hook (_Phase , {custom , _ }) -> true ;
420+ validate_hook (_Phase , {custom , _ , _ }) -> true ;
402421% % as well as status hooks
403422validate_hook (status , _ ) -> true ;
404423% % deny all others
405424validate_hook (_ , _ ) -> false .
406425
407- hook_filename ({custom , CustomScript }) -> CustomScript ;
408- hook_filename (pid ) -> " hooks/builtin/pid" ;
409- hook_filename ({pid , _ }) -> " hooks/builtin/pid" ;
410- hook_filename (wait_for_vm_start ) -> " hooks/builtin/wait_for_vm_start" ;
411- hook_filename ({wait_for_process , _ }) -> " hooks/builtin/wait_for_process" ;
412- hook_filename (builtin_status ) -> " hooks/builtin/status" .
413-
414- hook_invocation ({custom , CustomScript }) -> CustomScript ;
426+ % custom hook target location defaults to `bin/hooks`
427+ hook_filename ({custom , Src }) ->
428+ filename :join ([" bin/hooks" , filename :basename (Src )]);
429+ hook_filename ({custom , _ , Target }) -> Target ;
430+ hook_filename (pid ) -> " bin/hooks/builtin/pid" ;
431+ hook_filename ({pid , _ }) -> " bin/hooks/builtin/pid" ;
432+ hook_filename (wait_for_vm_start ) -> " bin/hooks/builtin/wait_for_vm_start" ;
433+ hook_filename ({wait_for_process , _ }) -> " bin/hooks/builtin/wait_for_process" ;
434+ hook_filename (builtin_status ) -> " bin/hooks/builtin/status" .
435+
436+ hook_invocation ({custom , Src }) ->
437+ filename :join ([" bin/hooks" , filename :basename (Src )]);
438+ hook_invocation ({custom , _ , Target }) ->
439+ Target ;
415440% % the pid builtin hook with no arguments writes to pid file
416441% % at /var/run/{{ rel_name }}.pid
417- hook_invocation (pid ) -> rlx_string :join ([" hooks/builtin/pid" ,
442+ hook_invocation (pid ) -> rlx_string :join ([" bin/ hooks/builtin/pid" ,
418443 " /var/run/$REL_NAME.pid" ], " |" );
419- hook_invocation ({pid , PidFile }) -> rlx_string :join ([" hooks/builtin/pid" ,
444+ hook_invocation ({pid , PidFile }) -> rlx_string :join ([" bin/ hooks/builtin/pid" ,
420445 PidFile ], " |" );
421- hook_invocation (wait_for_vm_start ) -> " hooks/builtin/wait_for_vm_start" ;
446+ hook_invocation (wait_for_vm_start ) -> " bin/ hooks/builtin/wait_for_vm_start" ;
422447hook_invocation ({wait_for_process , Name }) ->
423448 % % wait_for_process takes an atom as argument
424449 % % which is the process name to wait for
425- rlx_string :join ([" hooks/builtin/wait_for_process" ,
450+ rlx_string :join ([" bin/ hooks/builtin/wait_for_process" ,
426451 atom_to_list (Name )], " |" );
427- hook_invocation (builtin_status ) -> " hooks/builtin/status" .
452+ hook_invocation (builtin_status ) -> " bin/ hooks/builtin/status" .
428453
429- hook_template ({custom , _ }) -> custom ;
454+ hook_template ({custom , Src }) -> {file , Src };
455+ hook_template ({custom , Src , _ }) -> {file , Src };
430456hook_template (pid ) -> builtin_hook_pid ;
431457hook_template ({pid , _ }) -> builtin_hook_pid ;
432458hook_template (wait_for_vm_start ) -> builtin_hook_wait_for_vm_start ;
433459hook_template ({wait_for_process , _ }) -> builtin_hook_wait_for_process ;
434460hook_template (builtin_status ) -> builtin_hook_status .
435461
436- % % custom hooks are not rendered, they should
437- % % be copied by the release overlays
438- render_hook (custom , _ , _ ) -> ok ;
439462render_hook (TemplateName , Script , _State ) ->
440463 ? log_info (" rendering ~p hook to ~s " , [TemplateName , rlx_file_utils :print_path (Script )]),
441464 Template = render (TemplateName ),
@@ -966,6 +989,38 @@ bin_file_contents(Type, RelName, RelVsn, ErtsVsn) ->
966989 render (Template , [{rel_name , RelName }, {rel_vsn , RelVsn },
967990 {erts_vsn , ErtsVsn }]).
968991
992+ extension_default_target (Src ) ->
993+ filename :join (" bin/extensions" , filename :basename (Src )).
994+
995+ extension_default_description (_ ) ->
996+ " " .
997+
998+ extensions (Extensions ) ->
999+ extensions (Extensions , {[], [], []}).
1000+
1001+ extensions ([], {ExtensionsList0 , ExtensionDeclarations0 , ExtensionDescriptions0 }) ->
1002+ % pipe separated string of extensions
1003+ % (eg. foo|bar|baz|undefined)
1004+ ExtensionsList = rlx_string :join (ExtensionsList0 ++ [" undefined" ], " |" ),
1005+ % command separated string of extension script declarations
1006+ % (eg. foo_extension="path/to/foo_script:bar_extension="path/to/bar_script")
1007+ ExtensionDeclarations = rlx_string :join (ExtensionDeclarations0 , " ;" ),
1008+ % (eg. baz=baz description|foo=foo description|bar=)
1009+ ExtensionDescriptions = rlx_string :join (ExtensionDescriptions0 , " |" ),
1010+ {ExtensionsList , ExtensionDeclarations , ExtensionDescriptions };
1011+ extensions ([{Name , Src } | Rest ], Acc ) ->
1012+ extensions ([{Name , Src , extension_default_target (Src ), extension_default_description (Name )} | Rest ], Acc );
1013+ extensions ([{Name , Src , Description } | Rest ], Acc ) ->
1014+ extensions ([{Name , Src , extension_default_target (Src ), Description } | Rest ], Acc );
1015+ extensions ([{Name , _Src , Target , Description } | Rest ],
1016+ {Acc0 , Acc1 , Acc2 }) ->
1017+ NameStr = atom_to_list (Name ),
1018+ % eg. bar_extension=bin/extensions/bar
1019+ ExtensionDeclaration = NameStr ++ " _extension=\" " ++ Target ++ " \" " ,
1020+ % eg. bar=bar description
1021+ ExtensionDescription = NameStr ++ " =" ++ Description ,
1022+ extensions (Rest , {[atom_to_list (Name ) | Acc0 ], [ExtensionDeclaration | Acc1 ], [ExtensionDescription | Acc2 ]}).
1023+
9691024extended_bin_file_contents (Type , RelName , RelVsn , ErtsVsn , Hooks , Extensions ) ->
9701025 Template = case Type of
9711026 unix -> extended_bin ;
@@ -982,21 +1037,7 @@ extended_bin_file_contents(Type, RelName, RelVsn, ErtsVsn, Hooks, Extensions) ->
9821037 PostInstallUpgradeHooks = rlx_string :join (proplists :get_value (post_install_upgrade ,
9831038 Hooks , []), " " ),
9841039 StatusHook = rlx_string :join (proplists :get_value (status , Hooks , []), " " ),
985- {ExtensionsList1 , ExtensionDeclarations1 } =
986- lists :foldl (fun ({Name , Script },
987- {ExtensionsList0 , ExtensionDeclarations0 }) ->
988- ExtensionDeclaration = atom_to_list (Name ) ++
989- " _extension=\" " ++
990- Script ++ " \" " ,
991- {ExtensionsList0 ++ [atom_to_list (Name )],
992- ExtensionDeclarations0 ++ [ExtensionDeclaration ]}
993- end , {[], []}, Extensions ),
994- % pipe separated string of extensions, to show on the start script usage
995- % (eg. foo|bar)
996- ExtensionsList = rlx_string :join (ExtensionsList1 ++ [" undefined" ], " |" ),
997- % command separated string of extension script declarations
998- % (eg. foo_extension="path/to/foo_script")
999- ExtensionDeclarations = rlx_string :join (ExtensionDeclarations1 , " ;" ),
1040+ {ExtensionsList , ExtensionDeclarations , ExtensionDescriptions } = extensions (Extensions ),
10001041 render (Template , [{rel_name , RelName }, {rel_vsn , RelVsn },
10011042 {erts_vsn , ErtsVsn },
10021043 {pre_start_hooks , PreStartHooks },
@@ -1007,7 +1048,8 @@ extended_bin_file_contents(Type, RelName, RelVsn, ErtsVsn, Hooks, Extensions) ->
10071048 {post_install_upgrade_hooks , PostInstallUpgradeHooks },
10081049 {status_hook , StatusHook },
10091050 {extensions , ExtensionsList },
1010- {extension_declarations , ExtensionDeclarations }]).
1051+ {extension_declarations , ExtensionDeclarations },
1052+ {extension_descriptions , ExtensionDescriptions }]).
10111053
10121054install_upgrade_escript_contents () ->
10131055 render (install_upgrade_escript ).
@@ -1027,6 +1069,10 @@ vm_args_file(RelName) ->
10271069render (Template ) ->
10281070 render (Template , []).
10291071
1072+ render ({file , Name }, Data ) ->
1073+ {ok , Tpl } = file :read_file (Name ),
1074+ {ok , Content } = rlx_util :render (Tpl , Data ),
1075+ Content ;
10301076render (Template , Data ) ->
10311077 Files = rlx_util :template_files (),
10321078 Tpl = rlx_util :load_file (Files , escript , atom_to_list (Template )),
0 commit comments