diff options
Diffstat (limited to 'src/rebar_appups.erl')
-rw-r--r-- | src/rebar_appups.erl | 219 |
1 files changed, 0 insertions, 219 deletions
diff --git a/src/rebar_appups.erl b/src/rebar_appups.erl deleted file mode 100644 index 38e7b72..0000000 --- a/src/rebar_appups.erl +++ /dev/null @@ -1,219 +0,0 @@ -%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- -%% ex: ts=4 sw=4 et -%% ------------------------------------------------------------------- -%% -%% rebar: Erlang Build Tools -%% -%% Copyright (c) 2011 Joe Williams (joe@joetify.com) -%% -%% Permission is hereby granted, free of charge, to any person obtaining a copy -%% of this software and associated documentation files (the "Software"), to deal -%% in the Software without restriction, including without limitation the rights -%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -%% copies of the Software, and to permit persons to whom the Software is -%% furnished to do so, subject to the following conditions: -%% -%% The above copyright notice and this permission notice shall be included in -%% all copies or substantial portions of the Software. -%% -%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -%% THE SOFTWARE. -%% ------------------------------------------------------------------ - --module(rebar_appups). - --include("rebar.hrl"). - --export(['generate-appups'/2]). - -%% for internal use only --export([info/2]). - --define(APPUPFILEFORMAT, "%% appup generated for ~p by rebar (~p)~n" - "{~p, [{~p, ~p}], [{~p, []}]}.~n"). - -%% ==================================================================== -%% Public API -%% ==================================================================== - -'generate-appups'(Config, ReltoolFile) -> - %% Get the old release path - {Config1, ReltoolConfig} = rebar_rel_utils:load_config(Config, ReltoolFile), - TargetParentDir = rebar_rel_utils:get_target_parent_dir(Config, - ReltoolConfig), - - PrevRelPath = rebar_rel_utils:get_previous_release_path(Config), - OldVerPath = filename:join([TargetParentDir, PrevRelPath]), - - ModDeps = rebar_config:get(Config, module_deps, []), - - %% Get the new and old release name and versions - {Name, _Ver} = rebar_rel_utils:get_reltool_release_info(ReltoolConfig), - NewVerPath = filename:join([TargetParentDir, Name]), - {NewName, NewVer} = rebar_rel_utils:get_rel_release_info(Name, NewVerPath), - {OldName, OldVer} = rebar_rel_utils:get_rel_release_info(Name, OldVerPath), - - %% Run some simple checks - true = rebar_utils:prop_check(NewVer =/= OldVer, - "New and old .rel versions match~n", []), - true = rebar_utils:prop_check( - NewName == OldName, - "Reltool and .rel release names do not match~n", []), - - %% Find all the apps that have been upgraded - {_Added, _Removed, Upgraded} = get_apps(Name, OldVerPath, NewVerPath), - - %% Get a list of any appup files that exist in the new release - NewAppUpFiles = rebar_utils:find_files( - filename:join([NewVerPath, "lib"]), "^[^._].*.appup$"), - - %% Convert the list of appup files into app names - AppUpApps = [file_to_name(File) || File <- NewAppUpFiles], - - %% Create a list of apps that don't already have appups - UpgradeApps = genappup_which_apps(Upgraded, AppUpApps), - - %% Generate appup files for upgraded apps - generate_appup_files(NewVerPath, OldVerPath, ModDeps, UpgradeApps), - - {ok, Config1}. - -%% =================================================================== -%% Internal functions -%% =================================================================== - -info(help, 'generate-appups') -> - ?CONSOLE("Generate appup files.~n" - "~n" - "Valid command line options:~n" - " previous_release=path~n", - []). - -get_apps(Name, OldVerPath, NewVerPath) -> - OldApps = rebar_rel_utils:get_rel_apps(Name, OldVerPath), - ?DEBUG("Old Version Apps: ~p~n", [OldApps]), - - NewApps = rebar_rel_utils:get_rel_apps(Name, NewVerPath), - ?DEBUG("New Version Apps: ~p~n", [NewApps]), - - Added = app_list_diff(NewApps, OldApps), - ?DEBUG("Added: ~p~n", [Added]), - - Removed = app_list_diff(OldApps, NewApps), - ?DEBUG("Removed: ~p~n", [Removed]), - - PossiblyUpgraded = proplists:get_keys(NewApps), - - UpgradedApps = [upgraded_app(AppName, - proplists:get_value(AppName, OldApps), - proplists:get_value(AppName, NewApps)) - || AppName <- PossiblyUpgraded], - - Upgraded = lists:dropwhile(fun(Elem) -> - Elem == false - end, lists:sort(UpgradedApps)), - - ?DEBUG("Upgraded: ~p~n", [Upgraded]), - - {Added, Removed, Upgraded}. - -upgraded_app(AppName, OldAppVer, NewAppVer) when OldAppVer /= NewAppVer -> - {AppName, {OldAppVer, NewAppVer}}; -upgraded_app(_, _, _) -> - false. - -app_list_diff(List1, List2) -> - List3 = lists:umerge(lists:sort(proplists:get_keys(List1)), - lists:sort(proplists:get_keys(List2))), - List3 -- proplists:get_keys(List2). - -file_to_name(File) -> - filename:rootname(filename:basename(File)). - -genappup_which_apps(UpgradedApps, [First|Rest]) -> - List = proplists:delete(list_to_atom(First), UpgradedApps), - genappup_which_apps(List, Rest); -genappup_which_apps(Apps, []) -> - Apps. - -generate_appup_files(NewVerPath, OldVerPath, ModDeps, [{_App, {undefined, _}}|Rest]) -> - generate_appup_files(NewVerPath, OldVerPath, ModDeps, Rest); -generate_appup_files(NewVerPath, OldVerPath, ModDeps, [{App, {OldVer, NewVer}}|Rest]) -> - OldEbinDir = filename:join([OldVerPath, "lib", - atom_to_list(App) ++ "-" ++ OldVer, "ebin"]), - NewEbinDir = filename:join([NewVerPath, "lib", - atom_to_list(App) ++ "-" ++ NewVer, "ebin"]), - - {AddedFiles, DeletedFiles, ChangedFiles} = beam_lib:cmp_dirs(NewEbinDir, - OldEbinDir), - - ChangedNames = [list_to_atom(file_to_name(F)) || {F, _} <- ChangedFiles], - ModDeps1 = [{N, [M1 || M1 <- M, lists:member(M1, ChangedNames)]} - || {N, M} <- ModDeps], - - Added = [generate_instruction(added, File) || File <- AddedFiles], - Deleted = [generate_instruction(deleted, File) || File <- DeletedFiles], - Changed = [generate_instruction(changed, ModDeps1, File) - || File <- ChangedFiles], - - Inst = lists:append([Added, Deleted, Changed]), - - AppUpFile = filename:join([NewEbinDir, atom_to_list(App) ++ ".appup"]), - - ok = file:write_file(AppUpFile, - io_lib:fwrite(?APPUPFILEFORMAT, - [App, rebar_utils:now_str(), NewVer, - OldVer, Inst, OldVer])), - - ?CONSOLE("Generated appup for ~p~n", [App]), - generate_appup_files(NewVerPath, OldVerPath, ModDeps, Rest); -generate_appup_files(_, _, _, []) -> - ?CONSOLE("Appup generation complete~n", []). - -generate_instruction(added, File) -> - Name = list_to_atom(file_to_name(File)), - {add_module, Name}; -generate_instruction(deleted, File) -> - Name = list_to_atom(file_to_name(File)), - {delete_module, Name}. - -generate_instruction(changed, ModDeps, {File, _}) -> - {ok, {Name, List}} = beam_lib:chunks(File, [attributes, exports]), - Behavior = get_behavior(List), - CodeChange = is_code_change(List), - Deps = proplists:get_value(Name, ModDeps, []), - generate_instruction_advanced(Name, Behavior, CodeChange, Deps). - -generate_instruction_advanced(Name, undefined, undefined, Deps) -> - %% Not a behavior or code change, assume purely functional - {load_module, Name, Deps}; -generate_instruction_advanced(Name, [supervisor], _, _) -> - %% Supervisor - {update, Name, supervisor}; -generate_instruction_advanced(Name, _, code_change, Deps) -> - %% Includes code_change export - {update, Name, {advanced, []}, Deps}; -generate_instruction_advanced(Name, _, _, Deps) -> - %% Anything else - {load_module, Name, Deps}. - -get_behavior(List) -> - Attributes = proplists:get_value(attributes, List), - case proplists:get_value(behavior, Attributes) of - undefined -> proplists:get_value(behaviour, Attributes); - Else -> Else - end. - -is_code_change(List) -> - Exports = proplists:get_value(exports, List), - case proplists:is_defined(code_change, Exports) of - true -> - code_change; - false -> - undefined - end. |