diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/rebar.erl | 13 | ||||
-rw-r--r-- | src/rebar_app_utils.erl | 16 | ||||
-rw-r--r-- | src/rebar_appups.erl | 26 | ||||
-rw-r--r-- | src/rebar_config.erl | 20 | ||||
-rw-r--r-- | src/rebar_core.erl | 21 | ||||
-rw-r--r-- | src/rebar_ct.erl | 18 | ||||
-rw-r--r-- | src/rebar_deps.erl | 6 | ||||
-rw-r--r-- | src/rebar_erlc_compiler.erl | 12 | ||||
-rw-r--r-- | src/rebar_otp_app.erl | 2 | ||||
-rw-r--r-- | src/rebar_port_compiler.erl | 7 | ||||
-rw-r--r-- | src/rebar_rel_utils.erl | 78 | ||||
-rw-r--r-- | src/rebar_reltool.erl | 61 | ||||
-rw-r--r-- | src/rebar_subdirs.erl | 37 | ||||
-rw-r--r-- | src/rebar_templater.erl | 15 | ||||
-rw-r--r-- | src/rebar_upgrade.erl | 90 | ||||
-rw-r--r-- | src/rebar_utils.erl | 40 |
16 files changed, 301 insertions, 161 deletions
diff --git a/src/rebar.erl b/src/rebar.erl index 7f33d4d..c0c6c97 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -98,8 +98,19 @@ run_aux(Commands) -> %% Keep track of how many operations we do, so we can detect bad commands erlang:put(operations, 0), + %% If $HOME/.rebar/config exists load and use as global config + GlobalConfigFile = filename:join([os:getenv("HOME"), ".rebar", "config"]), + GlobalConfig = case filelib:is_regular(GlobalConfigFile) of + true -> + ?DEBUG("Load global config file ~p~n", + [GlobalConfigFile]), + rebar_config:new(GlobalConfigFile); + false -> + rebar_config:new() + end, + %% Process each command, resetting any state between each one - rebar_core:process_commands(CommandAtoms). + rebar_core:process_commands(CommandAtoms, GlobalConfig). %% %% print help/usage string diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl index 7e6cbd9..285bb5e 100644 --- a/src/rebar_app_utils.erl +++ b/src/rebar_app_utils.erl @@ -45,18 +45,26 @@ is_app_dir() -> is_app_dir(rebar_utils:get_cwd()). is_app_dir(Dir) -> - AppSrc = filename:join(Dir, "src/*.app.src"), + SrcDir = filename:join([Dir, "src"]), + AppSrc = filename:join([SrcDir, "*.app.src"]), case filelib:wildcard(AppSrc) of [AppSrcFile] -> {true, AppSrcFile}; - _ -> - App = filename:join([Dir, "ebin/*.app"]), + [] -> + EbinDir = filename:join([Dir, "ebin"]), + App = filename:join([EbinDir, "*.app"]), case filelib:wildcard(App) of [AppFile] -> {true, AppFile}; + [] -> + false; _ -> + ?ERROR("More than one .app file in ~s~n", [EbinDir]), false - end + end; + _ -> + ?ERROR("More than one .app.src file in ~s~n", [SrcDir]), + false end. diff --git a/src/rebar_appups.erl b/src/rebar_appups.erl index 871c426..923dad5 100644 --- a/src/rebar_appups.erl +++ b/src/rebar_appups.erl @@ -40,11 +40,15 @@ 'generate-appups'(_Config, ReltoolFile) -> %% Get the old release path - OldVerPath = rebar_rel_utils:get_previous_release_path(), + ReltoolConfig = rebar_rel_utils:load_config(ReltoolFile), + TargetParentDir = rebar_rel_utils:get_target_parent_dir(ReltoolConfig), + + OldVerPath = filename:join([TargetParentDir, + rebar_rel_utils:get_previous_release_path()]), %% Get the new and old release name and versions - {Name, _Ver} = rebar_rel_utils:get_reltool_release_info(ReltoolFile), - NewVerPath = filename:join([".", Name]), + {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), @@ -60,7 +64,7 @@ %% Get a list of any appup files that exist in the new release NewAppUpFiles = rebar_utils:find_files( - filename:join([NewName, "lib"]), "^.*.appup$"), + filename:join([NewVerPath, "lib"]), "^.*.appup$"), %% Convert the list of appup files into app names AppUpApps = [file_to_name(File) || File <- NewAppUpFiles], @@ -69,7 +73,7 @@ UpgradeApps = genappup_which_apps(Upgraded, AppUpApps), %% Generate appup files for upgraded apps - generate_appup_files(Name, OldVerPath, UpgradeApps), + generate_appup_files(NewVerPath, OldVerPath, UpgradeApps), ok. @@ -124,10 +128,12 @@ genappup_which_apps(UpgradedApps, [First|Rest]) -> genappup_which_apps(Apps, []) -> Apps. -generate_appup_files(Name, OldVerPath, [{App, {OldVer, NewVer}}|Rest]) -> - OldEbinDir = filename:join([".", OldVerPath, "lib", +generate_appup_files(NewVerPath, OldVerPath, [{_App, {undefined, _}}|Rest]) -> + generate_appup_files(NewVerPath, OldVerPath, Rest); +generate_appup_files(NewVerPath, OldVerPath, [{App, {OldVer, NewVer}}|Rest]) -> + OldEbinDir = filename:join([OldVerPath, "lib", atom_to_list(App) ++ "-" ++ OldVer, "ebin"]), - NewEbinDir = filename:join([".", Name, "lib", + NewEbinDir = filename:join([NewVerPath, "lib", atom_to_list(App) ++ "-" ++ NewVer, "ebin"]), {AddedFiles, DeletedFiles, ChangedFiles} = beam_lib:cmp_dirs(NewEbinDir, @@ -147,7 +153,7 @@ generate_appup_files(Name, OldVerPath, [{App, {OldVer, NewVer}}|Rest]) -> OldVer, Inst, OldVer])), ?CONSOLE("Generated appup for ~p~n", [App]), - generate_appup_files(Name, OldVerPath, Rest); + generate_appup_files(NewVerPath, OldVerPath, Rest); generate_appup_files(_, _, []) -> ?CONSOLE("Appup generation complete~n", []). @@ -174,7 +180,7 @@ generate_instruction_advanced(Name, _, code_change) -> {update, Name, {advanced, []}}; generate_instruction_advanced(Name, _, _) -> %% Anything else - {update, Name}. + {load_module, Name}. get_behavior(List) -> Attributes = proplists:get_value(attributes, List), diff --git a/src/rebar_config.erl b/src/rebar_config.erl index 751e088..9d2acf3 100644 --- a/src/rebar_config.erl +++ b/src/rebar_config.erl @@ -52,7 +52,15 @@ new() -> #config { dir = rebar_utils:get_cwd(), opts = []}. -new(ParentConfig) -> +new(ConfigFile) when is_list(ConfigFile) -> + case consult_file(ConfigFile) of + {ok, Opts} -> + #config { dir = rebar_utils:get_cwd(), + opts = Opts }; + Other -> + ?ABORT("Failed to load ~s: ~p~n", [ConfigFile, Other]) + end; +new(#config{opts=Opts0}=ParentConfig)-> %% If we are at the top level we might want to load another rebar.config %% We can be certain that we are at the top level if we don't have any %% configs yet since if we are at another level we must have some config. @@ -66,7 +74,7 @@ new(ParentConfig) -> %% Load terms from rebar.config, if it exists Dir = rebar_utils:get_cwd(), ConfigFile = filename:join([Dir, ConfName]), - Opts = case file:consult(ConfigFile) of + Opts = case consult_file(ConfigFile) of {ok, Terms} -> %% Found a config file with some terms. We need to %% be able to distinguish between local definitions @@ -75,10 +83,10 @@ new(ParentConfig) -> %% in the proplist (since order matters) between %% the new and old defs. Terms ++ [local] ++ - [Opt || Opt <- ParentConfig#config.opts, Opt /= local]; + [Opt || Opt <- Opts0, Opt /= local]; {error, enoent} -> [local] ++ - [Opt || Opt <- ParentConfig#config.opts, Opt /= local]; + [Opt || Opt <- Opts0, Opt /= local]; Other -> ?ABORT("Failed to load ~s: ~p\n", [ConfigFile, Other]) end, @@ -126,6 +134,10 @@ get_jobs() -> %% Internal functions %% =================================================================== +consult_file(File) -> + ?DEBUG("Consult config file ~p~n", [File]), + file:consult(File). + local_opts([], Acc) -> lists:reverse(Acc); local_opts([local | _Rest], Acc) -> diff --git a/src/rebar_core.erl b/src/rebar_core.erl index cb2c508..790edc9 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -26,7 +26,7 @@ %% ------------------------------------------------------------------- -module(rebar_core). --export([process_commands/1, +-export([process_commands/2, skip_dir/1, is_skip_dir/1, skip_dirs/0]). @@ -63,7 +63,7 @@ skip_dirs() -> %% Internal functions %% =================================================================== -process_commands([]) -> +process_commands([], _ParentConfig) -> case erlang:get(operations) of 0 -> %% none of the commands had an effect @@ -71,7 +71,7 @@ process_commands([]) -> _ -> ok end; -process_commands([Command | Rest]) -> +process_commands([Command | Rest], ParentConfig) -> %% Reset skip dirs lists:foreach(fun (D) -> erlang:erase({skip_dir, D}) end, skip_dirs()), Operations = erlang:get(operations), @@ -80,7 +80,7 @@ process_commands([Command | Rest]) -> %% If not, code:set_path() may choke on invalid relative paths when trying %% to restore the code path from inside a subdirectory. true = rebar_utils:expand_code_path(), - _ = process_dir(rebar_utils:get_cwd(), rebar_config:new(), + _ = process_dir(rebar_utils:get_cwd(), ParentConfig, Command, sets:new()), case erlang:get(operations) of Operations -> @@ -89,7 +89,7 @@ process_commands([Command | Rest]) -> _ -> ok end, - process_commands(Rest). + process_commands(Rest, ParentConfig). process_dir(Dir, ParentConfig, Command, DirSet) -> @@ -241,8 +241,15 @@ execute_plugin_hook(Hook, Command, Modules, Config, ModuleFile) -> execute(Command, Modules, Config, ModuleFile) -> case select_modules(Modules, Command, []) of [] -> - ?WARN("'~p' command does not apply to directory ~s\n", - [Command, rebar_utils:get_cwd()]); + Cmd = atom_to_list(Command), + case lists:prefix("pre_", Cmd) + orelse lists:prefix("post_", Cmd) of + true -> + ok; + false -> + ?WARN("'~p' command does not apply to directory ~s\n", + [Command, rebar_utils:get_cwd()]) + end; TargetModules -> %% Provide some info on where we are diff --git a/src/rebar_ct.erl b/src/rebar_ct.erl index 7ce6142..1b5ceff 100644 --- a/src/rebar_ct.erl +++ b/src/rebar_ct.erl @@ -46,8 +46,20 @@ %% =================================================================== ct(Config, File) -> - run_test_if_present("test", Config, File). - + case rebar_config:get_global(app, undefined) of + undefined -> + %% No app parameter specified, run everything.. + run_test_if_present("test", Config, File); + Apps -> + TargetApps = [list_to_atom(A) || A <- string:tokens(Apps, ",")], + ThisApp = rebar_app_utils:app_name(File), + case lists:member(ThisApp, TargetApps) of + true -> + run_test_if_present("test", Config, File); + false -> + ?DEBUG("Skipping common_test on app: ~p\n", [ThisApp]) + end + end. %% =================================================================== %% Internal functions @@ -90,7 +102,7 @@ clear_log(RawLog) -> %% log results check_log(RawLog) -> {ok, Msg} = - rebar_utils:sh("grep -e 'TEST COMPLETE' -e '{error,make_failed}' " + rebar_utils:sh("egrep -e 'TEST COMPLETE' -e '{error,make_failed}' " ++ RawLog, [{use_stdout, false}]), MakeFailed = string:str(Msg, "{error,make_failed}") =/= 0, RunFailed = string:str(Msg, ", 0 failed") =:= 0, diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl index fe73ca5..ac6add8 100644 --- a/src/rebar_deps.erl +++ b/src/rebar_deps.erl @@ -411,7 +411,11 @@ update_source(AppDir, {bzr, _Url, Rev}) -> %% Source helper functions %% =================================================================== -source_engine_avail({Name, _, _}=Source) +source_engine_avail(Source) -> + Name = element(1, Source), + source_engine_avail(Name, Source). + +source_engine_avail(Name, Source) when Name == hg; Name == git; Name == svn; Name == bzr -> case scm_client_vsn(Name) >= required_scm_client_vsn(Name) of true -> diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 8b63321..335283d 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -87,15 +87,19 @@ compile(Config, _AppFile) -> Config, yrl_first_files, [])), "src", ".yrl", "src", ".erl", fun compile_yrl/3), - doterl_compile(Config, "ebin"), rebar_base_compiler:run(Config, check_files(rebar_config:get_local( Config, mib_first_files, [])), "mibs", ".mib", "priv/mibs", ".bin", - fun compile_mib/3). + fun compile_mib/3), + doterl_compile(Config, "ebin"). -spec clean(Config::rebar_config:config(), AppFile::file:filename()) -> 'ok'. clean(_Config, _AppFile) -> + MibFiles = rebar_utils:find_files("mibs", "^.*\\.mib\$"), + MIBs = [filename:rootname(filename:basename(MIB)) || MIB <- MibFiles], + rebar_file_utils:delete_each( + [filename:join(["include",MIB++".hrl"]) || MIB <- MIBs]), lists:foreach(fun(F) -> ok = rebar_file_utils:rm_rf(F) end, ["ebin/*.beam", "priv/mibs/*.bin"]), @@ -270,6 +274,10 @@ compile_mib(Source, Target, Config) -> rebar_config:get(Config, mib_opts, []), case snmpc:compile(Source, Opts) of {ok, _} -> + Mib = filename:rootname(Target), + ok = snmpc:mib_to_hrl(Mib), + Hrl_filename = Mib ++ ".hrl", + rebar_file_utils:mv(Hrl_filename,"include"), ok; {error, compilation_failed} -> ?FAIL diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl index f92de5c..89730a6 100644 --- a/src/rebar_otp_app.erl +++ b/src/rebar_otp_app.erl @@ -150,7 +150,7 @@ validate_name(AppName, File) -> end. validate_modules(AppName, undefined) -> - ?ERROR("Missing modules declaration in~p.app:\n", [AppName]), + ?ERROR("Missing modules declaration in ~p.app~n", [AppName]), ?FAIL; validate_modules(AppName, Mods) -> diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl index b9c2ea4..c2430e7 100644 --- a/src/rebar_port_compiler.erl +++ b/src/rebar_port_compiler.erl @@ -399,7 +399,12 @@ default_env() -> %% OS X Snow Leopard flags for 32-bit {"darwin10.*-32", "CFLAGS", "-m32 $CFLAGS"}, {"darwin10.*-32", "CXXFLAGS", "-m32 $CXXFLAGS"}, - {"darwin10.*-32", "LDFLAGS", "-arch i386 $LDFLAGS"} + {"darwin10.*-32", "LDFLAGS", "-arch i386 $LDFLAGS"}, + + %% OS X Lion flags for 32-bit + {"darwin11.*-32", "CFLAGS", "-m32 $CFLAGS"}, + {"darwin11.*-32", "CXXFLAGS", "-m32 $CXXFLAGS"}, + {"darwin11.*-32", "LDFLAGS", "-arch i386 $LDFLAGS"} ]. diff --git a/src/rebar_rel_utils.erl b/src/rebar_rel_utils.erl index 0b14a28..bdf58d3 100644 --- a/src/rebar_rel_utils.erl +++ b/src/rebar_rel_utils.erl @@ -34,7 +34,11 @@ get_rel_apps/1, get_rel_apps/2, get_previous_release_path/0, - get_rel_file_path/2]). + get_rel_file_path/2, + load_config/1, + get_sys_tuple/1, + get_target_dir/1, + get_target_parent_dir/1]). -include("rebar.hrl"). @@ -51,16 +55,11 @@ is_rel_dir(Dir) -> end. %% Get release name and version from a reltool.config -get_reltool_release_info(ReltoolFile) -> - %% expect sys to be the first proplist in reltool.config - case file:consult(ReltoolFile) of - {ok, [{sys, Config}| _]} -> - %% expect the first rel in the proplist to be the one you want - {rel, Name, Ver, _} = proplists:lookup(rel, Config), - {Name, Ver}; - _ -> - ?ABORT("Failed to parse ~s~n", [ReltoolFile]) - end. +get_reltool_release_info(ReltoolConfig) -> + %% expect the first rel in the proplist to be the one you want + {sys, Config} = get_sys_tuple(ReltoolConfig), + {rel, Name, Ver, _} = proplists:lookup(rel, Config), + {Name, Ver}. %% Get release name and version from a rel file get_rel_release_info(RelFile) -> @@ -107,6 +106,59 @@ get_previous_release_path() -> OldVerPath end. +%% +%% Load terms from reltool.config +%% +load_config(ReltoolFile) -> + case file:consult(ReltoolFile) of + {ok, Terms} -> + Terms; + Other -> + ?ABORT("Failed to load expected config from ~s: ~p\n", + [ReltoolFile, Other]) + end. + +%% +%% Look for the {sys, [...]} tuple in the reltool.config file. +%% Without this present, we can't run reltool. +%% +get_sys_tuple(ReltoolConfig) -> + case lists:keyfind(sys, 1, ReltoolConfig) of + {sys, _} = SysTuple -> + SysTuple; + false -> + ?ABORT("Failed to find {sys, [...]} tuple in reltool.config.", []) + end. + +%% +%% Look for {target_dir, TargetDir} in the reltool config file; if none is +%% found, use the name of the release as the default target directory. +%% +get_target_dir(ReltoolConfig) -> + case rebar_config:get_global(target_dir, undefined) of + undefined -> + case lists:keyfind(target_dir, 1, ReltoolConfig) of + {target_dir, TargetDir} -> + filename:absname(TargetDir); + false -> + {sys, SysInfo} = get_sys_tuple(ReltoolConfig), + case lists:keyfind(rel, 1, SysInfo) of + {rel, Name, _Vsn, _Apps} -> + filename:absname(Name); + false -> + filename:absname("target") + end + end; + TargetDir -> + filename:absname(TargetDir) + end. + +get_target_parent_dir(ReltoolConfig) -> + case lists:reverse(tl(lists:reverse(filename:split(get_target_dir(ReltoolConfig))))) of + [] -> "."; + Components -> filename:join(Components) + end. + %% =================================================================== %% Internal functions %% =================================================================== @@ -114,8 +166,8 @@ get_previous_release_path() -> make_proplist([{_,_}=H|T], Acc) -> make_proplist(T, [H|Acc]); make_proplist([H|T], Acc) -> - App = erlang:element(1, H), - Ver = erlang:element(2, H), + App = element(1, H), + Ver = element(2, H), make_proplist(T, [{App,Ver}|Acc]); make_proplist([], Acc) -> Acc. diff --git a/src/rebar_reltool.erl b/src/rebar_reltool.erl index 72bfe49..b1b4a4c 100644 --- a/src/rebar_reltool.erl +++ b/src/rebar_reltool.erl @@ -42,14 +42,16 @@ generate(Config, ReltoolFile) -> check_vsn(), %% Load the reltool configuration from the file - ReltoolConfig = load_config(ReltoolFile), + ReltoolConfig = rebar_rel_utils:load_config(ReltoolFile), + + Sys = rebar_rel_utils:get_sys_tuple(ReltoolConfig), %% Spin up reltool server and load our config into it - {ok, Server} = reltool:start_server([sys_tuple(ReltoolConfig)]), + {ok, Server} = reltool:start_server([Sys]), %% Do some validation of the reltool configuration; error messages out of %% reltool are still pretty cryptic - validate_rel_apps(Server, sys_tuple(ReltoolConfig)), + validate_rel_apps(Server, Sys), %% Finally, run reltool case catch(run_reltool(Server, Config, ReltoolConfig)) of @@ -64,8 +66,8 @@ generate(Config, ReltoolFile) -> clean(_Config, ReltoolFile) -> - ReltoolConfig = load_config(ReltoolFile), - TargetDir = target_dir(ReltoolConfig), + ReltoolConfig = rebar_rel_utils:load_config(ReltoolFile), + TargetDir = rebar_rel_utils:get_target_dir(ReltoolConfig), rebar_file_utils:rm_rf(TargetDir), rebar_file_utils:delete_each(["reltool.spec"]). @@ -92,53 +94,6 @@ check_vsn() -> end. %% -%% Load terms from reltool.config -%% -load_config(ReltoolFile) -> - case file:consult(ReltoolFile) of - {ok, Terms} -> - Terms; - Other -> - ?ABORT("Failed to load expected config from ~s: ~p\n", - [ReltoolFile, Other]) - end. - -%% -%% Look for the {sys, [...]} tuple in the reltool.config file. -%% Without this present, we can't run reltool. -%% -sys_tuple(ReltoolConfig) -> - case lists:keyfind(sys, 1, ReltoolConfig) of - {sys, _} = SysTuple -> - SysTuple; - false -> - ?ABORT("Failed to find {sys, [...]} tuple in reltool.config.", []) - end. - -%% -%% Look for {target_dir, TargetDir} in the reltool config file; if none is -%% found, use the name of the release as the default target directory. -%% -target_dir(ReltoolConfig) -> - case rebar_config:get_global(target_dir, undefined) of - undefined -> - case lists:keyfind(target_dir, 1, ReltoolConfig) of - {target_dir, TargetDir} -> - filename:absname(TargetDir); - false -> - {sys, SysInfo} = sys_tuple(ReltoolConfig), - case lists:keyfind(rel, 1, SysInfo) of - {rel, Name, _Vsn, _Apps} -> - filename:absname(Name); - false -> - filename:absname("target") - end - end; - TargetDir -> - filename:absname(TargetDir) - end. - -%% %% Look for overlay_vars file reference. If the user provides an overlay_vars on %% the command line (i.e. a global), the terms from that file OVERRIDE the one %% listed in reltool.config. To re-iterate, this means you can specify a @@ -203,7 +158,7 @@ run_reltool(Server, _Config, ReltoolConfig) -> case reltool:get_target_spec(Server) of {ok, Spec} -> %% Pull the target dir and make sure it exists - TargetDir = target_dir(ReltoolConfig), + TargetDir = rebar_rel_utils:get_target_dir(ReltoolConfig), mk_target_dir(TargetDir), %% Dump the spec, if necessary diff --git a/src/rebar_subdirs.erl b/src/rebar_subdirs.erl index b107978..119dacb 100644 --- a/src/rebar_subdirs.erl +++ b/src/rebar_subdirs.erl @@ -27,6 +27,7 @@ -module(rebar_subdirs). -include("rebar.hrl"). +-include_lib("kernel/include/file.hrl"). -export([preprocess/2]). @@ -37,6 +38,38 @@ preprocess(Config, _) -> %% Get the list of subdirs specified in the config (if any). Cwd = rebar_utils:get_cwd(), - Subdirs = [filename:join(Cwd, Dir) || - Dir <- rebar_config:get_local(Config, sub_dirs, [])], + Subdirs0 = rebar_config:get_local(Config, sub_dirs, []), + Check = check_loop(Cwd), + ok = lists:foreach(Check, Subdirs0), + Subdirs = [filename:join(Cwd, Dir) || Dir <- Subdirs0], {ok, Subdirs}. + +%% =================================================================== +%% Internal functions +%% =================================================================== + +check_loop(Cwd) -> + RebarConfig = filename:join(Cwd, "rebar.config"), + fun(Dir0) -> + IsSymlink = case file:read_link_info(Dir0) of + {ok, #file_info{type=symlink}} -> + {true, resolve_symlink(Dir0)}; + _ -> + {false, Dir0} + end, + case IsSymlink of + {false, Dir="."} -> + ?ERROR("infinite loop detected:~nsub_dirs" + " entry ~p in ~s~n", [Dir, RebarConfig]); + {true, Cwd} -> + ?ERROR("infinite loop detected:~nsub_dirs" + " entry ~p in ~s is a symlink to \".\"~n", + [Dir0, RebarConfig]); + _ -> + ok + end + end. + +resolve_symlink(Dir0) -> + {ok, Dir} = file:read_link(Dir0), + Dir. diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl index 76fa4d4..5fe427b 100644 --- a/src/rebar_templater.erl +++ b/src/rebar_templater.erl @@ -200,8 +200,8 @@ find_escript_templates() -> find_disk_templates() -> OtherTemplates = find_other_templates(), - HomeFiles = rebar_utils:find_files(filename:join(os:getenv("HOME"), - ".rebar/templates"), + HomeFiles = rebar_utils:find_files(filename:join([os:getenv("HOME"), + ".rebar", "templates"]), ?TEMPLATE_RE), LocalFiles = rebar_utils:find_files(".", ?TEMPLATE_RE), [{file, F} || F <- OtherTemplates ++ HomeFiles ++ LocalFiles]. @@ -359,6 +359,17 @@ execute_template([{dir, Name} | Rest], TemplateType, TemplateName, Context, ?ABORT("Failed while processing template instruction " "{dir, ~s}: ~p\n", [Name, Reason]) end; +execute_template([{copy, Input, Output} | Rest], TemplateType, TemplateName, + Context, Force, ExistingFiles) -> + InputName = filename:join(filename:dirname(TemplateName), Input), + try rebar_file_utils:cp_r([InputName ++ "/*"], Output) of + ok -> + execute_template(Rest, TemplateType, TemplateName, + Context, Force, ExistingFiles) + catch _:_ -> + ?ABORT("Failed while processing template instruction " + "{dir, ~s, ~s}~n", [Input, Output]) + end; execute_template([{chmod, Mod, File} | Rest], TemplateType, TemplateName, Context, Force, ExistingFiles) when is_integer(Mod) -> case file:change_mode(File, Mod) of diff --git a/src/rebar_upgrade.erl b/src/rebar_upgrade.erl index 0bf0338..009715e 100644 --- a/src/rebar_upgrade.erl +++ b/src/rebar_upgrade.erl @@ -38,29 +38,34 @@ 'generate-upgrade'(_Config, ReltoolFile) -> %% Get the old release path - OldVerPath = rebar_rel_utils:get_previous_release_path(), + ReltoolConfig = rebar_rel_utils:load_config(ReltoolFile), + TargetParentDir = rebar_rel_utils:get_target_parent_dir(ReltoolConfig), + TargetDir = rebar_rel_utils:get_target_dir(ReltoolConfig), + + OldVerPath = filename:join([TargetParentDir, + rebar_rel_utils:get_previous_release_path()]), %% Run checks to make sure that building a package is possible - {NewName, NewVer} = run_checks(OldVerPath, ReltoolFile), + {NewVerPath, NewName, NewVer} = run_checks(OldVerPath, ReltoolConfig), NameVer = NewName ++ "_" ++ NewVer, %% Save the code path prior to doing anything OrigPath = code:get_path(), %% Prepare the environment for building the package - ok = setup(OldVerPath, NewName, NewVer, NameVer), + ok = setup(OldVerPath, NewVerPath, NewName, NewVer, NameVer), %% Build the package run_systools(NameVer, NewName), %% Boot file changes - {ok, _} = boot_files(NewVer, NewName), + {ok, _} = boot_files(TargetDir, NewVer, NewName), %% Extract upgrade and tar it back up with changes make_tar(NameVer), %% Clean up files that systools created - ok = cleanup(NameVer, NewName, NewVer), + ok = cleanup(NameVer), %% Restore original path true = code:set_path(OrigPath), @@ -71,18 +76,19 @@ %% Internal functions %% ================================================================== -run_checks(OldVerPath, ReltoolFile) -> +run_checks(OldVerPath, ReltoolConfig) -> true = rebar_utils:prop_check(filelib:is_dir(OldVerPath), "Release directory doesn't exist (~p)~n", [OldVerPath]), - {Name, Ver} = rebar_rel_utils:get_reltool_release_info(ReltoolFile), + {Name, Ver} = rebar_rel_utils:get_reltool_release_info(ReltoolConfig), - NamePath = filename:join([".", Name]), - true = rebar_utils:prop_check(filelib:is_dir(NamePath), - "Release directory doesn't exist (~p)~n", [NamePath]), + NewVerPath = filename:join([ + rebar_rel_utils:get_target_parent_dir(ReltoolConfig), + Name]), + true = rebar_utils:prop_check(filelib:is_dir(NewVerPath), + "Release directory doesn't exist (~p)~n", [NewVerPath]), - {NewName, NewVer} = NewNameAndVer = - rebar_rel_utils:get_rel_release_info(Name, NamePath), + {NewName, NewVer} = rebar_rel_utils:get_rel_release_info(Name, NewVerPath), {OldName, OldVer} = rebar_rel_utils:get_rel_release_info(Name, OldVerPath), true = rebar_utils:prop_check(NewName == OldName, @@ -94,11 +100,10 @@ run_checks(OldVerPath, ReltoolFile) -> true = rebar_utils:prop_check(Ver == NewVer, "Reltool and .rel versions do not match~n", []), - NewNameAndVer. + {NewVerPath, NewName, NewVer}. -setup(OldVerPath, NewName, NewVer, NameVer) -> - NewRelPath = filename:join([".", NewName]), - Src = filename:join([NewRelPath, "releases", +setup(OldVerPath, NewVerPath, NewName, NewVer, NameVer) -> + Src = filename:join([NewVerPath, "releases", NewVer, NewName ++ ".rel"]), Dst = filename:join([".", NameVer ++ ".rel"]), {ok, _} = file:copy(Src, Dst), @@ -108,9 +113,9 @@ setup(OldVerPath, NewName, NewVer, NameVer) -> "releases", "*"])), filelib:wildcard(filename:join([OldVerPath, "lib", "*", "ebin"])), - filelib:wildcard(filename:join([NewRelPath, + filelib:wildcard(filename:join([NewVerPath, "lib", "*", "ebin"])), - filelib:wildcard(filename:join([NewRelPath, "*"])) + filelib:wildcard(filename:join([NewVerPath, "*"])) ])). run_systools(NewVer, Name) -> @@ -135,30 +140,35 @@ run_systools(NewVer, Name) -> end end. -boot_files(Ver, Name) -> - ok = file:make_dir(filename:join([".", "releases"])), - ok = file:make_dir(filename:join([".", "releases", Ver])), +boot_files(TargetDir, Ver, Name) -> + Tmp = "_tmp", + ok = file:make_dir(filename:join([".", Tmp])), + ok = file:make_dir(filename:join([".", Tmp, "releases"])), + ok = file:make_dir(filename:join([".", Tmp, "releases", Ver])), ok = file:make_symlink( filename:join(["start.boot"]), - filename:join([".", "releases", Ver, Name ++ ".boot"])), + filename:join([".", Tmp, "releases", Ver, Name ++ ".boot"])), {ok, _} = file:copy( - filename:join([".", Name, "releases", Ver, "start_clean.boot"]), - filename:join([".", "releases", Ver, "start_clean.boot"])). + filename:join([TargetDir, "releases", Ver, "start_clean.boot"]), + filename:join([".", Tmp, "releases", Ver, "start_clean.boot"])). make_tar(NameVer) -> Filename = NameVer ++ ".tar.gz", - ok = erl_tar:extract(Filename, [compressed]), - ok = file:delete(Filename), - {ok, Tar} = erl_tar:open(Filename, [write, compressed]), + {ok, Cwd} = file:get_cwd(), + Absname = filename:join([Cwd, Filename]), + ok = file:set_cwd("_tmp"), + ok = erl_tar:extract(Absname, [compressed]), + ok = file:delete(Absname), + {ok, Tar} = erl_tar:open(Absname, [write, compressed]), ok = erl_tar:add(Tar, "lib", []), ok = erl_tar:add(Tar, "releases", []), ok = erl_tar:close(Tar), + ok = file:set_cwd(Cwd), ?CONSOLE("~s upgrade package created~n", [NameVer]). -cleanup(NameVer, Name, Ver) -> +cleanup(NameVer) -> ?DEBUG("Removing files needed for building the upgrade~n", []), Files = [ - filename:join([".", "releases", Ver, Name ++ ".boot"]), filename:join([".", NameVer ++ ".rel"]), filename:join([".", NameVer ++ ".boot"]), filename:join([".", NameVer ++ ".script"]), @@ -166,18 +176,17 @@ cleanup(NameVer, Name, Ver) -> ], lists:foreach(fun(F) -> ok = file:delete(F) end, Files), - ok = remove_dir_tree("releases"), - ok = remove_dir_tree("lib"). + ok = remove_dir_tree("_tmp"). -%% taken from http://www.erlang.org/doc/system_principles/create_target.html +%% adapted from http://www.erlang.org/doc/system_principles/create_target.html remove_dir_tree(Dir) -> remove_all_files(".", [Dir]). remove_all_files(Dir, Files) -> lists:foreach(fun(File) -> FilePath = filename:join([Dir, File]), - {ok, FileInfo} = file:read_file_info(FilePath), - case FileInfo#file_info.type of - directory -> + {ok, FileInfo, Link} = file_info(FilePath), + case {Link, FileInfo#file_info.type} of + {false, directory} -> {ok, DirFiles} = file:list_dir(FilePath), remove_all_files(FilePath, DirFiles), file:del_dir(FilePath); @@ -185,3 +194,14 @@ remove_all_files(Dir, Files) -> file:delete(FilePath) end end, Files). + +file_info(Path) -> + case file:read_file_info(Path) of + {ok, Info} -> + {ok, Info, false}; + {error, enoent} -> + {ok, Info} = file:read_link_info(Path), + {ok, Info, true}; + Error -> + Error + end. diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index f18621b..4571d17 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -41,7 +41,7 @@ find_executable/1, prop_check/3, expand_code_path/0, - deprecated/4, deprecated/5]). + deprecated/5]). -include("rebar.hrl"). @@ -102,8 +102,8 @@ sh(Command0, Options0) -> case sh_loop(Port, OutputHandler, []) of {ok, _Output} = Ok -> Ok; - {error, Rc} -> - ErrorHandler(Command, Rc) + {error, Err} -> + ErrorHandler(Command, Err) end. %% We need a bash shell to execute on windows @@ -182,12 +182,12 @@ expand_code_path() -> expand_sh_flag(return_on_error) -> {error_handler, - fun(_Command, Rc) -> - {error, Rc} + fun(_Command, Err) -> + {error, Err} end}; expand_sh_flag({abort_on_error, Message}) -> {error_handler, - fun(_Command, _Rc) -> + fun(_Command, _Err) -> ?ABORT(Message, []) end}; expand_sh_flag(abort_on_error) -> @@ -197,12 +197,12 @@ expand_sh_flag(use_stdout) -> {output_handler, fun(Line, Acc) -> ?CONSOLE("~s", [Line]), - [Acc | Line] + [Line | Acc] end}; expand_sh_flag({use_stdout, false}) -> {output_handler, fun(Line, Acc) -> - [Acc | Line] + [Line | Acc] end}; expand_sh_flag({cd, _CdArg} = Cd) -> {port_settings, Cd}; @@ -210,8 +210,8 @@ expand_sh_flag({env, _EnvArg} = Env) -> {port_settings, Env}. -spec log_and_abort(string(), integer()) -> no_return(). -log_and_abort(Command, Rc) -> - ?ABORT("~s failed with error: ~w\n", [Command, Rc]). +log_and_abort(Command, {Rc, Output}) -> + ?ABORT("~s failed with error: ~w and output:~n~s~n", [Command, Rc, Output]). sh_loop(Port, Fun, Acc) -> receive @@ -226,9 +226,9 @@ sh_loop(Port, Fun, Acc) -> {Port, {data, {noeol, Line}}} -> sh_loop(Port, Fun, Fun(Line, Acc)); {Port, {exit_status, 0}} -> - {ok, lists:flatten(Acc)}; + {ok, lists:flatten(lists:reverse(Acc))}; {Port, {exit_status, Rc}} -> - {error, Rc} + {error, {Rc, lists:flatten(lists:reverse(Acc))}} end. beam_to_mod(Dir, Filename) -> @@ -264,16 +264,12 @@ emulate_escript_foldl(Fun, Acc, File) -> deprecated(Key, Old, New, Opts, When) -> case lists:member(Old, Opts) of true -> - deprecated(Key, Old, New, When); + io:format( + <<"WARNING: deprecated ~p option used~n" + "Option '~p' has been deprecated~n" + "in favor of '~p'.~n" + "'~p' will be removed ~s.~n~n">>, + [Key, Old, New, Old, When]); false -> ok end. - -deprecated(Key, Old, New, When) -> - io:format( - << - "WARNING: deprecated ~p option used~n" - "Option '~p' has been deprecated~n" - "in favor of '~p'.~n" - "'~p' will be removed ~s.~n~n" - >>, [Key, Old, New, Old, When]). |