From 6304c19180ec2e0c1f00145e86719e228195823a Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Mon, 13 Dec 2010 13:07:33 +0100 Subject: Revert to using awk instead of cut --- priv/templates/simplenode.runner | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/priv/templates/simplenode.runner b/priv/templates/simplenode.runner index cfde552..262cc1e 100755 --- a/priv/templates/simplenode.runner +++ b/priv/templates/simplenode.runner @@ -70,16 +70,16 @@ case "$1" in Linux|Darwin|FreeBSD|DragonFly|NetBSD|OpenBSD) # PID COMMAND PID=`ps ax -o pid= -o command=|\ - grep "$RUNNER_BASE_DIR/.*/[b]eam"|cut -d' ' -f1` + grep "$RUNNER_BASE_DIR/.*/[b]eam"|awk '{print $1}'` ;; SunOS) # PID COMMAND PID=`ps -ef -o pid= -o args=|\ - grep "$RUNNER_BASE_DIR/.*/[b]eam"|cut -d' ' -f1` + grep "$RUNNER_BASE_DIR/.*/[b]eam"|awk '{print $1}'` ;; CYGWIN*) # UID PID PPID TTY STIME COMMAND - PID=`ps -efW|grep "$RUNNER_BASE_DIR/.*/[b]eam"|cut -d' ' -f2` + PID=`ps -efW|grep "$RUNNER_BASE_DIR/.*/[b]eam"|awk '{print $2}'` ;; esac $NODETOOL stop -- cgit v1.1 From 9ecc3455bf071eb3a49443e1e709281864fdfeb3 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 14 Dec 2010 22:24:03 +0100 Subject: Fix typo in rebar_erlydtl_compiler --- src/rebar_erlydtl_compiler.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rebar_erlydtl_compiler.erl b/src/rebar_erlydtl_compiler.erl index b3cbd98..aa017ce 100644 --- a/src/rebar_erlydtl_compiler.erl +++ b/src/rebar_erlydtl_compiler.erl @@ -109,7 +109,7 @@ compile_dtl(Source, Target, Config) -> non_existing -> ?CONSOLE( "~n===============================================~n" - " You need to install erlydtl to comple DTL templates~n" + " You need to install erlydtl to compile DTL templates~n" " Download the latest tarball release from github~n" " http://code.google.com/p/erlydtl/~n" " and install it into your erlang library dir~n" -- cgit v1.1 From ec6a5fb587eced1e7040d8fbcc2db9d117c32c7a Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Thu, 16 Dec 2010 16:14:54 +0100 Subject: Add Anthony Ramine to THANKS file --- THANKS | 1 + 1 file changed, 1 insertion(+) diff --git a/THANKS b/THANKS index f94e1da..298eba6 100644 --- a/THANKS +++ b/THANKS @@ -34,3 +34,4 @@ Matthew Batema Alexey Romanov Benjamin Nortier Magnus Klaar +Anthony Ramine -- cgit v1.1 From 57e593a3190f9de9894f6ae990b26a23bbf32b48 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 17 Dec 2010 12:39:31 +0100 Subject: Fix possible export VAR=VALUE bashism --- priv/templates/simplenode.runner | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/priv/templates/simplenode.runner b/priv/templates/simplenode.runner index 262cc1e..10c233b 100755 --- a/priv/templates/simplenode.runner +++ b/priv/templates/simplenode.runner @@ -58,7 +58,8 @@ case "$1" in echo "Node is already running!" exit 1 fi - export HEART_COMMAND="$RUNNER_BASE_DIR/bin/$SCRIPT start" + HEART_COMMAND="$RUNNER_BASE_DIR/bin/$SCRIPT start" + export HEART_COMMAND mkdir -p $PIPE_DIR # Note the trailing slash on $PIPE_DIR/ $ERTS_PATH/run_erl -daemon $PIPE_DIR/ $RUNNER_LOG_DIR "exec $RUNNER_BASE_DIR/bin/$SCRIPT console" 2>&1 -- cgit v1.1 From d8e50e8c2d3af9234d27e8e5a652c5575d1493ad Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Thu, 9 Dec 2010 19:45:58 +0100 Subject: Implement update-deps and disable auto update --- priv/shell-completion/bash/rebar | 2 +- src/rebar_core.erl | 1 + src/rebar_deps.erl | 65 ++++++++++++++++++++++++++-------------- 3 files changed, 44 insertions(+), 24 deletions(-) diff --git a/priv/shell-completion/bash/rebar b/priv/shell-completion/bash/rebar index 237255c..ead10ff 100644 --- a/priv/shell-completion/bash/rebar +++ b/priv/shell-completion/bash/rebar @@ -10,7 +10,7 @@ _rebar() lopts=" --help --commands --verbose --force --jobs= --version" cmdsnvars="build-plt check-plt check-deps clean compile \ create create-app create-node ct dialyze doc delete-deps eunit \ - get-deps generate help list-templates version xref \ + get-deps generate help list-templates update-deps version xref \ case= debug_info=1 force=1 jobs= suite= verbose=1 appid= \ skip_deps=1 template= template_dir=" diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 3c64f8d..e8b4e57 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -223,6 +223,7 @@ doc Generate Erlang program documentation check-deps Display to be fetched dependencies get-deps Fetch dependencies +update-deps Update fetched dependencies delete-deps Delete fetched dependencies generate [dump_spec=0/1] Build release with reltool diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl index 0852b01..a86b83c 100644 --- a/src/rebar_deps.erl +++ b/src/rebar_deps.erl @@ -33,6 +33,7 @@ compile/2, 'check-deps'/2, 'get-deps'/2, + 'update-deps'/2, 'delete-deps'/2]). @@ -54,7 +55,7 @@ preprocess(Config, _) -> %% Get the list of deps for the current working directory and identify those %% deps that are available/present. Deps = rebar_config:get_local(Config, deps, []), - {AvailableDeps, MissingDeps} = find_deps(Deps), + {AvailableDeps, MissingDeps} = find_deps(find, Deps), ?DEBUG("Available deps: ~p\n", [AvailableDeps]), ?DEBUG("Missing deps : ~p\n", [MissingDeps]), @@ -93,7 +94,7 @@ compile(Config, AppFile) -> 'check-deps'(Config, _) -> %% Get the list of immediate (i.e. non-transitive) deps that are missing Deps = rebar_config:get_local(Config, deps, []), - case find_deps(Deps) of + case find_deps(find, Deps) of {_, []} -> %% No missing deps ok; @@ -108,26 +109,31 @@ compile(Config, AppFile) -> 'get-deps'(Config, _) -> %% Determine what deps are available and missing Deps = rebar_config:get_local(Config, deps, []), - {AvailableDeps, MissingDeps} = find_deps(Deps), + {_AvailableDeps, MissingDeps} = find_deps(find, Deps), %% For each missing dep with a specified source, try to pull it. - PulledDeps0 = [use_source(D) || D <- MissingDeps, D#dep.source /= undefined], - - %% For each available dep try to update the source to the specified - %% version. - PulledDeps1 = [update_source(D) || D <- AvailableDeps, - D#dep.source /= undefined], + PulledDeps = [use_source(D) || D <- MissingDeps, D#dep.source /= undefined], %% Add each pulled dep to our list of dirs for post-processing. This yields %% the necessary transitivity of the deps - erlang:put(?MODULE, [D#dep.dir || D <- PulledDeps0 ++ PulledDeps1]), + erlang:put(?MODULE, [D#dep.dir || D <- PulledDeps]), + ok. + +'update-deps'(Config, _) -> + %% Determine what deps are available and missing + Deps = rebar_config:get_local(Config, deps, []), + UpdatedDeps = [update_source(D) || D <- find_deps(read, Deps), + D#dep.source /= undefined], + %% Add each updated dep to our list of dirs for post-processing. This yields + %% the necessary transitivity of the deps + erlang:put(?MODULE, [D#dep.dir || D <- UpdatedDeps]), ok. 'delete-deps'(Config, _) -> %% Delete all the available deps in our deps/ directory, if any DepsDir = get_deps_dir(), Deps = rebar_config:get_local(Config, deps, []), - {AvailableDeps, _} = find_deps(Deps), + {AvailableDeps, _} = find_deps(find, Deps), _ = [delete_dep(D) || D <- AvailableDeps, lists:prefix(DepsDir, D#dep.dir) == true], ok. @@ -163,35 +169,48 @@ update_deps_code_path([Dep | Rest]) -> end, update_deps_code_path(Rest). -find_deps(Deps) -> - find_deps(Deps, {[], []}). -find_deps([], {Avail, Missing}) -> +find_deps(find=Mode, Deps) -> + find_deps(Mode, Deps, {[], []}); +find_deps(read=Mode, Deps) -> + find_deps(Mode, Deps, []). + +find_deps(find, [], {Avail, Missing}) -> {lists:reverse(Avail), lists:reverse(Missing)}; -find_deps([App | Rest], Acc) when is_atom(App) -> - find_deps([{App, ".*", undefined} | Rest], Acc); -find_deps([{App, VsnRegex} | Rest], Acc) when is_atom(App) -> - find_deps([{App, VsnRegex, undefined} | Rest], Acc); -find_deps([{App, VsnRegex, Source} | Rest], {Avail, Missing}) -> +find_deps(read, [], Deps) -> + lists:reverse(Deps); +find_deps(Mode, [App | Rest], Acc) when is_atom(App) -> + find_deps(Mode, [{App, ".*", undefined} | Rest], Acc); +find_deps(Mode, [{App, VsnRegex} | Rest], Acc) when is_atom(App) -> + find_deps(Mode, [{App, VsnRegex, undefined} | Rest], Acc); +find_deps(Mode, [{App, VsnRegex, Source} | Rest], Acc) -> Dep = #dep { app = App, vsn_regex = VsnRegex, source = Source }, case is_app_available(App, VsnRegex) of {true, AppDir} -> - find_deps(Rest, {[Dep#dep { dir = AppDir } | Avail], Missing}); + find_deps(Mode, Rest, acc_deps(Mode, avail, Dep, AppDir, Acc)); {false, _} -> AppDir = filename:join(get_deps_dir(), Dep#dep.app), case is_app_available(App, VsnRegex, AppDir) of {true, AppDir} -> - find_deps(Rest, {[Dep#dep { dir = AppDir } | Avail], Missing}); + find_deps(Mode, Rest, + acc_deps(Mode, avail, Dep, AppDir, Acc)); {false, _} -> - find_deps(Rest, {Avail, [Dep#dep { dir = AppDir } | Missing]}) + find_deps(Mode, Rest, + acc_deps(Mode, missing, Dep, AppDir, Acc)) end end; -find_deps([Other | _Rest], _Acc) -> +find_deps(_Mode, [Other | _Rest], _Acc) -> ?ABORT("Invalid dependency specification ~p in ~s\n", [Other, rebar_utils:get_cwd()]). +acc_deps(find, avail, Dep, AppDir, {Avail, Missing}) -> + {[Dep#dep { dir = AppDir } | Avail], Missing}; +acc_deps(find, missing, Dep, AppDir, {Avail, Missing}) -> + {Avail, [Dep#dep { dir = AppDir } | Missing]}; +acc_deps(read, _, Dep, AppDir, Acc) -> + [Dep#dep { dir = AppDir } | Acc]. delete_dep(D) -> case filelib:is_dir(D#dep.dir) of -- cgit v1.1 From 9b0d35d9869801d6ee52fde8ba443b07d95892e8 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Mon, 20 Dec 2010 08:55:31 -0700 Subject: Adding support for app_vars in external file --- src/rebar_otp_app.erl | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl index a8a4ecd..7cb70df 100644 --- a/src/rebar_otp_app.erl +++ b/src/rebar_otp_app.erl @@ -41,7 +41,7 @@ compile(Config, File) -> %% be validated as usual. AppFile = case rebar_app_utils:is_app_src(File) of true -> - preprocess(File); + preprocess(Config, File); false -> File end, @@ -86,12 +86,14 @@ clean(_Config, File) -> %% Internal functions %% =================================================================== -preprocess(AppSrcFile) -> +preprocess(Config, AppSrcFile) -> case rebar_app_utils:load_app_file(AppSrcFile) of {ok, AppName, AppData} -> - %% Get a list of all the modules available in ebin/ and update - %% the app data accordingly - A1 = lists:keystore(modules, 1, AppData, {modules, ebin_modules()}), + %% Look for a configuration file with vars we want to + %% substitute. Note that we include the list of modules available in + %% ebin/ and update the app data accordingly. + AppVars = load_app_vars(Config) ++ [{modules, ebin_modules()}], + A1 = apply_app_vars(AppVars, AppData), %% Build the final spec as a string Spec = io_lib:format("~p.\n", [{application, AppName, A1}]), @@ -109,6 +111,22 @@ preprocess(AppSrcFile) -> ?ABORT("Failed to read ~s for preprocessing: ~p\n", [AppSrcFile, Reason]) end. +load_app_vars(Config) -> + case rebar_config:get_local(Config, app_vars_file, undefined) of + undefined -> + ?INFO("No app_vars_file defined.\n", []), + []; + Filename -> + ?INFO("Loading app vars from ~p\n", [Filename]), + {ok, Vars} = file:consult(Filename), + Vars + end. + +apply_app_vars([], AppData) -> + AppData; +apply_app_vars([{Key, Value} | Rest], AppData) -> + AppData2 = lists:keystore(Key, 1, AppData, {Key, Value}), + apply_app_vars(Rest, AppData2). validate_name(AppName, File) -> %% Convert the .app file name to an atom -- check it against the identifier within the file -- cgit v1.1 From 63d5ceb61d68af7f1847e3442a1d3f56b6808672 Mon Sep 17 00:00:00 2001 From: David Reid Date: Thu, 11 Nov 2010 09:41:13 -0800 Subject: Support single level of nested template variables Add support for defining template variables of the following form: {variables, [{appid, "mochiwebapp"}, {author, "Mochi Media "}, {year, "2010"}, {version, "0.1"}, {port, 8080}, {dest, "{{appid}}"}]}. Where dest may be overridden on the commandline but will default to being the appid. Mochiweb uses this so that we can create new projects from the template in a configurable directory. So $ rebar create template=mochiwebapp dest=foo appid=bar I thought about special casing dest but figured it might be generally useful to be able to nest template vars. However this patch only does one level of resolution. So if {variables, [{foo, "{{bar}}"}, {bar, "{{foo}}"}]}. then bar will end up being the literal string {{bar}} and foo the literal string {{foo}}. --- src/rebar_templater.erl | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl index 4aa5ed6..e251f40 100644 --- a/src/rebar_templater.erl +++ b/src/rebar_templater.erl @@ -104,8 +104,14 @@ create(_Config, _) -> %% For each variable, see if it's defined in global vars -- if it is, prefer that %% value over the defaults - Context = update_vars(dict:fetch_keys(Context0), Context0), - ?DEBUG("Template ~p context: ~p\n", [template_id(), dict:to_list(Context)]), + Context1 = update_vars(dict:fetch_keys(Context0), Context0), + ?DEBUG("Template ~p context: ~p\n", [template_id(), dict:to_list(Context1)]), + + %% Handle variables that possibly include other variables in their + %% definition + Context = resolve_recursive_vars(dict:to_list(Context1), Context1), + + ?DEBUG("Resolved Template ~p context: ~p\n", [template_id(), dict:to_list(Context1)]), %% Now, use our context to process the template definition -- this permits us to %% use variables within the definition for filenames. @@ -206,6 +212,19 @@ update_vars([Key | Rest], Dict) -> %% +%% Given a list of key value pairs, for each string value attempt to +%% render it using Dict as the context. Storing the result in Dict as Key. +%% + +resolve_recursive_vars([], Dict) -> + Dict; +resolve_recursive_vars([{Key, Value0} | Rest], Dict) when is_list(Value0) -> + Value = render(list_to_binary(Value0), Dict), + resolve_recursive_vars(Rest, dict:store(Key, Value, Dict)); +resolve_recursive_vars([_Pair | Rest], Dict) -> + resolve_recursive_vars(Rest, Dict). + +%% %% Given a string or binary, parse it into a list of terms, ala file:consult/0 %% consult(Str) when is_list(Str) -> @@ -319,4 +338,3 @@ execute_template([{variables, _} | Rest], TemplateType, TemplateName, Context, F execute_template([Other | Rest], TemplateType, TemplateName, Context, Force, ExistingFiles) -> ?WARN("Skipping unknown template instruction: ~p\n", [Other]), execute_template(Rest, TemplateType, TemplateName, Context, Force, ExistingFiles). - -- cgit v1.1 From 008dcb8542ed4bb1aed98e3fed92c55b0770d132 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 15 Dec 2010 15:08:15 +0100 Subject: Add abnfc support abnfc is an ABNF parser generator. Options are: - doc_root (defaults to "src") - out_dir (defaults to "src") - source_ext (defaults to ".abnf") - module_ext (defaults to "") --- ebin/rebar.app | 2 + src/rebar_abnfc_compiler.erl | 109 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 src/rebar_abnfc_compiler.erl diff --git a/ebin/rebar.app b/ebin/rebar.app index 6f9b6f5..ad37c66 100644 --- a/ebin/rebar.app +++ b/ebin/rebar.app @@ -2,6 +2,7 @@ [{description, "Rebar: Erlang Build Tool"}, {vsn, "2"}, {modules, [ rebar, + rebar_abnfc_compiler, rebar_app_utils, rebar_base_compiler, rebar_config, @@ -59,6 +60,7 @@ {modules, [ {app_dir, [ rebar_pre_script, + rebar_abnfc_compiler, rebar_protobuffs_compiler, rebar_neotoma_compiler, rebar_asn1_compiler, diff --git a/src/rebar_abnfc_compiler.erl b/src/rebar_abnfc_compiler.erl new file mode 100644 index 0000000..743b3fe --- /dev/null +++ b/src/rebar_abnfc_compiler.erl @@ -0,0 +1,109 @@ +%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% ex: ts=4 sw=4 et +%% ------------------------------------------------------------------- +%% +%% rebar: Erlang Build Tools +%% +%% Copyright (c) 2010 Anthony Ramine (nox@dev-extend.eu), +%% +%% 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. +%% ------------------------------------------------------------------- + +%% The rebar_abnfc_compiler module is a plugin for rebar that compiles +%% ABNF grammars into parsers. By default, it compiles all src/*.abnf +%% to src/*.erl. +%% +%% Configuration options should be placed in rebar.config under +%% 'abnfc_opts'. Available options include: +%% +%% doc_root: where to find the ABNF grammars to compile +%% "src" by default +%% +%% out_dir: where to put the generated files. +%% "src" by default +%% +%% source_ext: the file extension the ABNF grammars have. +%% ".abnf" by default +%% +%% module_ext: characters to append to the parser's module name +%% "" by default +-module(rebar_abnfc_compiler). + +-export([compile/2]). + +-include("rebar.hrl"). + +%% =================================================================== +%% Public API +%% =================================================================== + +compile(Config, _AppFile) -> + DtlOpts = abnfc_opts(Config), + rebar_base_compiler:run(Config, [], + option(doc_root, DtlOpts), + option(source_ext, DtlOpts), + option(out_dir, DtlOpts), + option(module_ext, DtlOpts) ++ ".erl", + fun compile_abnfc/3). + + +%% =================================================================== +%% Internal functions +%% =================================================================== + +abnfc_opts(Config) -> + rebar_config:get(Config, abnfc_opts, []). + +option(Opt, DtlOpts) -> + proplists:get_value(Opt, DtlOpts, default(Opt)). + +default(doc_root) -> "src"; +default(out_dir) -> "src"; +default(source_ext) -> ".abnf"; +default(module_ext) -> "". + +abnfc_is_present() -> + code:which(abnfc) =/= non_existing. + +compile_abnfc(Source, _Target, Config) -> + case abnfc_is_present() of + false -> + ?CONSOLE( + "~n===============================================~n" + " You need to install abnfc to compile ABNF grammars~n" + " Download the latest tarball release from github~n" + " https://github.com/nygge/abnfc~n" + " and install it into your erlang library dir~n" + "===============================================~n~n", []), + ?FAIL; + true -> + AbnfcOpts = abnfc_opts(Config), + SourceExt = option(source_ext, AbnfcOpts), + Opts = [noobj, + {o, option(out_dir, AbnfcOpts)}, + {mod, filename:basename(Source, SourceExt) ++ + option(module_ext, AbnfcOpts)}], + case abnfc:file(Source, Opts) of + ok -> ok; + Error -> + ?CONSOLE("Compiling grammar ~s failed:~n ~p~n", + [Source, Error]), + ?FAIL + end + end. -- cgit v1.1 From a529577b740d5a0a8f48703d4d66248099155de0 Mon Sep 17 00:00:00 2001 From: Joseph Wayne Norton Date: Mon, 27 Dec 2010 11:04:47 +0900 Subject: Remove erlc target after fail_on_warning failure Prevent overlooking a compilation warning by removing the target beam file after fail_on_warning failure. --- src/rebar_erlc_compiler.erl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index e69dea9..13c2eaa 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -228,6 +228,8 @@ internal_erl_compile(Source, Config, Outdir, ErlOpts) -> %% We got at least one warning -- if fail_on_warning is in options, fail case lists:member(fail_on_warning, Opts) of true -> + %% remove target to prevent overlooking this failure + ok = file:delete(Target), ?FAIL; false -> ok -- cgit v1.1 From 9c0d51bc0be4ae1f141ab25a12724d97ffc7c0a7 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Thu, 30 Dec 2010 14:32:49 +0100 Subject: Fix order of erl_opts to be more accurate --- src/rebar_erlc_compiler.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 13c2eaa..871b9a1 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -219,8 +219,8 @@ internal_erl_compile(Source, Config, Outdir, ErlOpts) -> %% the target, case needs_compile(Source, Target, Hrls) of true -> - Opts = [{i, "include"}, {outdir, filename:dirname(Target)}, report, return] ++ - ErlOpts, + Opts = [{outdir, filename:dirname(Target)}] ++ + ErlOpts ++ [{i, "include"}, report, return], case compile:file(Source, Opts) of {ok, _, []} -> ok; -- cgit v1.1 From f83f18eb3bcaebc746c72ffe728379c9a44668f1 Mon Sep 17 00:00:00 2001 From: Charles McKnight Date: Wed, 5 Jan 2011 16:00:00 -0800 Subject: Fix error where ebin was created as a file This patch remedies an issue where the ebin directory would be erroneously created as a file by the first "mv" command in rebar_protobuffs_compile.erl [line 106] if the ebin file did not exist at the root application level. In essence, the patch ensures that the ebin directory exists at the application directory level before any "mv" commands are executed. The following code was inserted at line 106: ok = filelib:ensure_dir(filename:join("ebin","dummy")), --- src/rebar_protobuffs_compiler.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rebar_protobuffs_compiler.erl b/src/rebar_protobuffs_compiler.erl index 122440c..2a2139f 100644 --- a/src/rebar_protobuffs_compiler.erl +++ b/src/rebar_protobuffs_compiler.erl @@ -103,6 +103,7 @@ compile_each([{Proto, Beam, Hrl} | Rest]) -> %% Compilation worked, but we need to move the .beam and .hrl file %% into the ebin/ and include/ directories respectively %% TODO: Protobuffs really needs to be better about this...sigh. + ok = filelib:ensure_dir(filename:join("ebin","dummy")), [] = os:cmd(?FMT("mv ~s ebin", [Beam])), ok = filelib:ensure_dir(filename:join("include", Hrl)), [] = os:cmd(?FMT("mv ~s include", [Hrl])), -- cgit v1.1 From f7eb0a71589ec4ebee1315fe2f430d8af607aa36 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Thu, 6 Jan 2011 12:30:58 +0100 Subject: Add Charles McKnight to THANKS file --- THANKS | 1 + 1 file changed, 1 insertion(+) diff --git a/THANKS b/THANKS index 298eba6..2cf87a9 100644 --- a/THANKS +++ b/THANKS @@ -35,3 +35,4 @@ Alexey Romanov Benjamin Nortier Magnus Klaar Anthony Ramine +Charles McKnight -- cgit v1.1 From 52ca7795feb001f0624ec87e717e3019f8a810bd Mon Sep 17 00:00:00 2001 From: Juhani Rankimies Date: Sun, 5 Dec 2010 02:07:12 +0200 Subject: Unify executable invocation Add flags to rebar_utils:sh to control output and error handling. Replace calls to os:cmd with calls to rebar_utils:sh. --- src/rebar_ct.erl | 6 ++- src/rebar_deps.erl | 40 +++++++------- src/rebar_erlydtl_compiler.erl | 16 +++--- src/rebar_file_utils.erl | 68 ++++++++++++++++-------- src/rebar_neotoma_compiler.erl | 15 ++++-- src/rebar_port_compiler.erl | 22 ++++---- src/rebar_post_script.erl | 3 +- src/rebar_pre_script.erl | 3 +- src/rebar_protobuffs_compiler.erl | 4 +- src/rebar_utils.erl | 106 +++++++++++++++++++++++++++----------- test/rebar_file_utils_tests.erl | 12 +++++ 11 files changed, 199 insertions(+), 96 deletions(-) diff --git a/src/rebar_ct.erl b/src/rebar_ct.erl index 316998f..d6d4675 100644 --- a/src/rebar_ct.erl +++ b/src/rebar_ct.erl @@ -71,7 +71,7 @@ run_test(TestDir, Config, _File) -> Output = " 2>&1 | tee -a " ++ RawLog end, - rebar_utils:sh(Cmd ++ Output, [{"TESTDIR", TestDir}]), + rebar_utils:sh(Cmd ++ Output, [{env,[{"TESTDIR", TestDir}]}]), check_log(RawLog). @@ -89,7 +89,9 @@ clear_log(RawLog) -> %% calling ct with erl does not return non-zero on failure - have to check %% log results check_log(RawLog) -> - Msg = os:cmd("grep -e 'TEST COMPLETE' -e '{error,make_failed}' " ++ RawLog), + {ok, Msg} = + rebar_utils:sh("grep -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, if diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl index a86b83c..ded75db 100644 --- a/src/rebar_deps.erl +++ b/src/rebar_deps.erl @@ -292,28 +292,31 @@ use_source(Dep, Count) -> download_source(AppDir, {hg, Url, Rev}) -> ok = filelib:ensure_dir(AppDir), - rebar_utils:sh(?FMT("hg clone -U ~s ~s", [Url, filename:basename(AppDir)]), [], filename:dirname(AppDir)), - rebar_utils:sh(?FMT("hg update ~s", [Rev]), [], AppDir); + rebar_utils:sh(?FMT("hg clone -U ~s ~s", [Url, filename:basename(AppDir)]), + [{cd, filename:dirname(AppDir)}]), + rebar_utils:sh(?FMT("hg update ~s", [Rev]), [{cd, AppDir}]); download_source(AppDir, {git, Url, {branch, Branch}}) -> ok = filelib:ensure_dir(AppDir), - rebar_utils:sh(?FMT("git clone -n ~s ~s", [Url, filename:basename(AppDir)]), [], filename:dirname(AppDir)), - rebar_utils:sh(?FMT("git checkout -q origin/~s", [Branch]), [], AppDir); + rebar_utils:sh(?FMT("git clone -n ~s ~s", [Url, filename:basename(AppDir)]), + [{cd, filename:dirname(AppDir)}]), + rebar_utils:sh(?FMT("git checkout -q origin/~s", [Branch]), [{cd, AppDir}]); download_source(AppDir, {git, Url, {tag, Tag}}) -> ok = filelib:ensure_dir(AppDir), - rebar_utils:sh(?FMT("git clone -n ~s ~s", [Url, filename:basename(AppDir)]), [], filename:dirname(AppDir)), - rebar_utils:sh(?FMT("git checkout -q ~s", [Tag]), [], AppDir); + rebar_utils:sh(?FMT("git clone -n ~s ~s", [Url, filename:basename(AppDir)]), + [{cd, filename:dirname(AppDir)}]), + rebar_utils:sh(?FMT("git checkout -q ~s", [Tag]), [{cd, AppDir}]); download_source(AppDir, {git, Url, Rev}) -> download_source(AppDir, {git, Url, {branch, Rev}}); download_source(AppDir, {bzr, Url, Rev}) -> ok = filelib:ensure_dir(AppDir), rebar_utils:sh(?FMT("bzr branch -r ~s ~s ~s", - [Rev, Url, filename:basename(AppDir)]), [], - filename:dirname(AppDir)); + [Rev, Url, filename:basename(AppDir)]), + [{cd, filename:dirname(AppDir)}]); download_source(AppDir, {svn, Url, Rev}) -> ok = filelib:ensure_dir(AppDir), rebar_utils:sh(?FMT("svn checkout -r ~s ~s ~s", - [Rev, Url, filename:basename(AppDir)]), [], - filename:dirname(AppDir)). + [Rev, Url, filename:basename(AppDir)]), + [{cd, filename:dirname(AppDir)}]). update_source(Dep) -> %% It's possible when updating a source, that a given dep does not have a @@ -333,19 +336,19 @@ update_source(Dep) -> end. update_source(AppDir, {git, _Url, {branch, Branch}}) -> - rebar_utils:sh(?FMT("git fetch origin", []), [], AppDir), - rebar_utils:sh(?FMT("git checkout -q origin/~s", [Branch]), [], AppDir); + rebar_utils:sh("git fetch origin", [{cd, AppDir}]), + rebar_utils:sh(?FMT("git checkout -q origin/~s", [Branch]), [{cd, AppDir}]); update_source(AppDir, {git, _Url, {tag, Tag}}) -> - rebar_utils:sh(?FMT("git fetch --tags origin", []), [], AppDir), - rebar_utils:sh(?FMT("git checkout -q ~s", [Tag]), [], AppDir); + rebar_utils:sh("git fetch --tags origin", [{cd, AppDir}]), + rebar_utils:sh(?FMT("git checkout -q ~s", [Tag]), [{cd, AppDir}]); update_source(AppDir, {git, Url, Refspec}) -> update_source(AppDir, {git, Url, {branch, Refspec}}); update_source(AppDir, {svn, _Url, Rev}) -> - rebar_utils:sh(?FMT("svn up -r ~s", [Rev]), [], AppDir); + rebar_utils:sh(?FMT("svn up -r ~s", [Rev]), [{cd, AppDir}]); update_source(AppDir, {hg, _Url, Rev}) -> - rebar_utils:sh(?FMT("hg pull -u -r ~s", [Rev]), [], AppDir); + rebar_utils:sh(?FMT("hg pull -u -r ~s", [Rev]), [{cd, AppDir}]); update_source(AppDir, {bzr, _Url, Rev}) -> - rebar_utils:sh(?FMT("bzr update -r ~s", [Rev]), [], AppDir). + rebar_utils:sh(?FMT("bzr update -r ~s", [Rev]), [{cd, AppDir}]). @@ -366,7 +369,8 @@ source_engine_avail({Name, _, _}=Source) scm_client_vsn(false, _VsnArg, _VsnRegex) -> false; scm_client_vsn(Path, VsnArg, VsnRegex) -> - Info = os:cmd("LANG=C " ++ Path ++ VsnArg), + {ok, Info} = rebar_utils:sh(Path ++ VsnArg, [{env, [{"LANG", "C"}]}, + {use_stdout, false}]), case re:run(Info, VsnRegex, [{capture, all_but_first, list}]) of {match, Match} -> list_to_tuple([list_to_integer(S) || S <- Match]); diff --git a/src/rebar_erlydtl_compiler.erl b/src/rebar_erlydtl_compiler.erl index aa017ce..6b2160c 100644 --- a/src/rebar_erlydtl_compiler.erl +++ b/src/rebar_erlydtl_compiler.erl @@ -162,11 +162,16 @@ referenced_dtls1(Step, Config, Seen) -> DtlOpts = erlydtl_opts(Config), ExtMatch = re:replace(option(source_ext, DtlOpts), "\.", "\\\\\\\\.", [{return, list}]), - AllRefs = lists:append( - [string:tokens( - os:cmd(["grep -o [^\\\"]*",ExtMatch," ",F]), - "\n") - || F <- Step]), + AllRefs = + lists:append( + lists:map( + fun(F) -> + {ok, Res} = rebar_utils:sh( + lists:flatten(["grep -o [^\\\"]*", + ExtMatch," ",F]), + [{use_stdout, false}]), + string:tokens(Res, "\n") + end, Step)), DocRoot = option(doc_root, DtlOpts), WithPaths = [ filename:join([DocRoot, F]) || F <- AllRefs ], Existing = [F || F <- WithPaths, filelib:is_file(F)], @@ -176,4 +181,3 @@ referenced_dtls1(Step, Config, Seen) -> _ -> referenced_dtls1(sets:to_list(New), Config, sets:union(New, Seen)) end. - diff --git a/src/rebar_file_utils.erl b/src/rebar_file_utils.erl index 1538fa8..0a7cd4c 100644 --- a/src/rebar_file_utils.erl +++ b/src/rebar_file_utils.erl @@ -28,6 +28,7 @@ -export([rm_rf/1, cp_r/2, + mv/2, delete_each/1]). -include("rebar.hrl"). @@ -42,25 +43,54 @@ -spec rm_rf(Target::string()) -> ok. rm_rf(Target) -> case os:type() of - {unix,_} -> - [] = os:cmd(?FMT("rm -rf ~s", [Target])), + {unix, _} -> + {ok, []} = rebar_utils:sh(?FMT("rm -rf ~s", [Target]), + [{use_stdout, false}, return_on_error]), ok; - {win32,_} -> - ok = rm_rf_win32(Target) + {win32, _} -> + Filelist = filelib:wildcard(Target), + Dirs = lists:filter(fun filelib:is_dir/1,Filelist), + Files = lists:subtract(Filelist,Dirs), + ok = delete_each(Files), + ok = delete_each_dir_win32(Dirs), + ok end. -spec cp_r(Sources::list(string()), Dest::string()) -> ok. cp_r(Sources, Dest) -> case os:type() of - {unix,_} -> + {unix, _} -> SourceStr = string:join(Sources, " "), - [] = os:cmd(?FMT("cp -R ~s ~s", [SourceStr, Dest])), + {ok, []} = rebar_utils:sh(?FMT("cp -R ~s ~s", [SourceStr, Dest]), + [{use_stdout, false}, return_on_error]), ok; - {win32,_} -> + {win32, _} -> lists:foreach(fun(Src) -> ok = cp_r_win32(Src,Dest) end, Sources), ok end. +-spec mv(Source::string(), Dest::string()) -> ok. +mv(Source, Dest) -> + case os:type() of + {unix, _} -> + {ok, []} = rebar_utils:sh(?FMT("mv ~s ~s", [Source, Dest]), + [{use_stdout, false}, return_on_error]), + ok; + {win32, _} -> + {ok, R} = rebar_utils:sh( + ?FMT("cmd " "/c move /y ~s ~s 1> nul", + [filename:nativename(Source), + filename:nativename(Dest)]), + [{use_stdout, false}, return_on_error]), + case length(R) == 0 of + true -> ok; + false -> + {error, lists:flatten( + io_lib:format("Failed to move ~s to ~s~n", + [Source, Dest]))} + end + end. + delete_each([]) -> ok; delete_each([File | Rest]) -> @@ -78,30 +108,26 @@ delete_each([File | Rest]) -> %% Internal functions %% =================================================================== -rm_rf_win32(Target) -> - Filelist = filelib:wildcard(Target), - Dirs = lists:filter(fun filelib:is_dir/1,Filelist), - Files = lists:subtract(Filelist,Dirs), - ok = delete_each(Files), - ok = delete_each_dir_win32(Dirs), - ok. - delete_each_dir_win32([]) -> ok; delete_each_dir_win32([Dir | Rest]) -> - [] = os:cmd(?FMT("rd /q /s ~s", [filename:nativename(Dir)])), + {ok, []} = rebar_utils:sh(?FMT("cmd /c rd /q /s ~s", + [filename:nativename(Dir)]), + [{use_stdout, false}, return_on_error]), delete_each_dir_win32(Rest). xcopy_win32(Source,Dest)-> - R = os:cmd(?FMT("xcopy ~s ~s /q /y /e 2> nul", - [filename:nativename(Source), filename:nativename(Dest)])), - case string:str(R,"\r\n") > 0 of + {ok, R} = rebar_utils:sh( + ?FMT("cmd /c xcopy ~s ~s /q /y /e 2> nul", + [filename:nativename(Source), filename:nativename(Dest)]), + [{use_stdout, false}, return_on_error]), + case length(R) > 0 of %% when xcopy fails, stdout is empty and and error message is printed %% to stderr (which is redirected to nul) true -> ok; false -> {error, lists:flatten( - io_lib:format("Failed to xcopy from ~s to ~s\n", - [Source, Dest]))} + io_lib:format("Failed to xcopy from ~s to ~s~n", + [Source, Dest]))} end. cp_r_win32({true,SourceDir},{true,DestDir}) -> diff --git a/src/rebar_neotoma_compiler.erl b/src/rebar_neotoma_compiler.erl index 89cd089..c2e6f0d 100644 --- a/src/rebar_neotoma_compiler.erl +++ b/src/rebar_neotoma_compiler.erl @@ -121,11 +121,16 @@ referenced_pegs1(Step, Config, Seen) -> NeoOpts = neotoma_opts(Config), ExtMatch = re:replace(option(source_ext, NeoOpts), "\.", "\\\\\\\\.", [{return, list}]), - AllRefs = lists:append( - [string:tokens( - os:cmd(["grep -o [^\\\"]*",ExtMatch," ",F]), - "\n") - || F <- Step]), + AllRefs = + lists:append( + lists:map( + fun(F) -> + {ok, Res} = rebar_utils:sh( + lists:flatten(["grep -o [^\\\"]*", + ExtMatch," ",F]), + [{use_stdout, false}]), + string:tokens(Res, "\n") + end, Step)), DocRoot = option(doc_root, NeoOpts), WithPaths = [ filename:join([DocRoot, F]) || F <- AllRefs ], Existing = [F || F <- WithPaths, filelib:is_file(F)], diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl index 732965c..c1a6500 100644 --- a/src/rebar_port_compiler.erl +++ b/src/rebar_port_compiler.erl @@ -89,7 +89,7 @@ compile(Config, AppFile) -> %% One or more files are available for building. Run the pre-compile hook, if %% necessary. - run_precompile_hook(Config, Env), + ok = run_precompile_hook(Config, Env), %% Compile each of the sources {NewBins, ExistingBins} = compile_each(Sources, Config, Env, [], []), @@ -103,8 +103,9 @@ compile(Config, AppFile) -> lists:foreach(fun({SoName,Bins}) -> case needs_link(SoName, sets:to_list(sets:intersection([sets:from_list(Bins),sets:from_list(NewBins)]))) of true -> - rebar_utils:sh_failfast(?FMT("$CC ~s $LDFLAGS $DRV_LDFLAGS -o ~s", - [string:join(Bins, " "), SoName]), Env); + rebar_utils:sh(?FMT("$CC ~s $LDFLAGS $DRV_LDFLAGS -o ~s", + [string:join(Bins, " "), SoName]), + [{env, Env}]); false -> ?INFO("Skipping relink of ~s\n", [SoName]), ok @@ -148,7 +149,8 @@ run_precompile_hook(Config, Env) -> case filelib:is_regular(BypassFileName) of false -> ?CONSOLE("Running ~s\n", [Script]), - rebar_utils:sh_failfast(Script, Env); + {ok, _} = rebar_utils:sh(Script, [{env, Env}]), + ok; true -> ?INFO("~s exists; not running ~s\n", [BypassFileName, Script]) end @@ -160,7 +162,8 @@ run_cleanup_hook(Config) -> ok; Script -> ?CONSOLE("Running ~s\n", [Script]), - rebar_utils:sh_failfast(Script, []) + {ok, _} = rebar_utils:sh(Script, []), + ok end. @@ -174,11 +177,12 @@ compile_each([Source | Rest], Config, Env, NewBins, ExistingBins) -> ?CONSOLE("Compiling ~s\n", [Source]), case compiler(Ext) of "$CC" -> - rebar_utils:sh_failfast(?FMT("$CC -c $CFLAGS $DRV_CFLAGS ~s -o ~s", - [Source, Bin]), Env); + rebar_utils:sh(?FMT("$CC -c $CFLAGS $DRV_CFLAGS ~s -o ~s", + [Source, Bin]), [{env, Env}]); "$CXX" -> - rebar_utils:sh_failfast(?FMT("$CXX -c $CXXFLAGS $DRV_CFLAGS ~s -o ~s", - [Source, Bin]), Env) + rebar_utils:sh( + ?FMT("$CXX -c $CXXFLAGS $DRV_CFLAGS ~s -o ~s", + [Source, Bin]), [{env, Env}]) end, compile_each(Rest, Config, Env, [Bin | NewBins], ExistingBins); diff --git a/src/rebar_post_script.erl b/src/rebar_post_script.erl index 04daec7..d83df1c 100644 --- a/src/rebar_post_script.erl +++ b/src/rebar_post_script.erl @@ -51,5 +51,6 @@ execute_post_script(Config, Key) -> undefined -> ok; Script -> - rebar_utils:sh(Script, []) + {ok, _} = rebar_utils:sh(Script, []), + ok end. diff --git a/src/rebar_pre_script.erl b/src/rebar_pre_script.erl index d2d7205..5b8fecd 100644 --- a/src/rebar_pre_script.erl +++ b/src/rebar_pre_script.erl @@ -51,5 +51,6 @@ execute_pre_script(Config, Key) -> undefined -> ok; Script -> - rebar_utils:sh(Script, []) + {ok, _} = rebar_utils:sh(Script, []), + ok end. diff --git a/src/rebar_protobuffs_compiler.erl b/src/rebar_protobuffs_compiler.erl index 2a2139f..eafed41 100644 --- a/src/rebar_protobuffs_compiler.erl +++ b/src/rebar_protobuffs_compiler.erl @@ -104,9 +104,9 @@ compile_each([{Proto, Beam, Hrl} | Rest]) -> %% into the ebin/ and include/ directories respectively %% TODO: Protobuffs really needs to be better about this...sigh. ok = filelib:ensure_dir(filename:join("ebin","dummy")), - [] = os:cmd(?FMT("mv ~s ebin", [Beam])), + ok = rebar_file_utils:mv(Beam, "ebin"), ok = filelib:ensure_dir(filename:join("include", Hrl)), - [] = os:cmd(?FMT("mv ~s include", [Hrl])), + ok = rebar_file_utils:mv(Hrl, "include"), ok; Other -> ?ERROR("Protobuff compile of ~s failed: ~p\n", [Proto, Other]), diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 98fdbd7..ae27455 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -30,8 +30,7 @@ is_arch/1, get_arch/0, get_os/0, - sh/2, sh/3, - sh_failfast/2, + sh/2, find_files/2, now_str/0, ensure_dir/1, @@ -73,36 +72,49 @@ get_os() -> ArchAtom end. +%% +%% Options = [Option] -- defaults to [use_stdout, abort_on_error] +%% Option = ErrorOption | OutputOption | {cd, string()} | {env, Env} +%% ErrorOption = return_on_error | abort_on_error | {abort_on_error, string()} +%% OutputOption = use_stdout | {use_stdout, bool()} +%% Env = [{string(), Val}] +%% Val = string() | false +%% +sh(Command0, Options0) -> + ?INFO("sh: ~s\n~p\n", [Command0, Options0]), -sh(Command, Env) -> - sh(Command, Env, get_cwd()). + DefaultOptions = [use_stdout, abort_on_error], + Options = lists:map(fun expand_sh_flag/1, + proplists:compact(Options0 ++ DefaultOptions)), -sh(Command0, Env, Dir) -> - ?INFO("sh: ~s\n~p\n", [Command0, Env]), - Command = patch_on_windows(Command0, os:type()), - Port = open_port({spawn, Command}, [{cd, Dir}, {env, Env}, exit_status, {line, 16384}, - use_stdio, stderr_to_stdout]), - case sh_loop(Port) of - ok -> - ok; + ErrorHandler = proplists:get_value(error_handler, Options), + OutputHandler = proplists:get_value(output_handler, Options), + + Command = patch_on_windows(Command0), + PortSettings = proplists:get_all_values(port_settings, Options) ++ + [exit_status, {line, 16384}, use_stdio, stderr_to_stdout, hide], + Port = open_port({spawn, Command}, PortSettings), + + case sh_loop(Port, OutputHandler, []) of + {ok, Output} -> + {ok, Output}; {error, Rc} -> - ?ABORT("~s failed with error: ~w\n", [Command, Rc]) + ErrorHandler(Command, Rc) end. - %% We need a bash shell to execute on windows %% also the port doesn't seem to close from time to time (mingw) -patch_on_windows(Cmd, {win32,nt}) -> - case find_executable("bash") of - false -> Cmd; - Bash -> - Bash ++ " -c \"" ++ Cmd ++ "; echo _port_cmd_status_ $?\" " - end; -patch_on_windows(Command, _) -> - Command. - -sh_failfast(Command, Env) -> - sh(Command, Env). +patch_on_windows(Cmd) -> + case os:type() of + {win32,nt} -> + case find_executable("bash") of + false -> Cmd; + Bash -> + Bash ++ " -c \"" ++ Cmd ++ "; echo _port_cmd_status_ $?\" " + end; + _ -> + Cmd + end. find_files(Dir, Regex) -> filelib:fold_files(Dir, Regex, true, fun(F, Acc) -> [F | Acc] end, []). @@ -162,19 +174,51 @@ match_first([{Regex, MatchValue} | Rest], Val) -> match_first(Rest, Val) end. -sh_loop(Port) -> +expand_sh_flag(return_on_error) -> + {error_handler, + fun(_Command, Rc) -> + {error, Rc} + end}; +expand_sh_flag({abort_on_error, Message}) -> + {error_handler, + fun(_Command, _Rc) -> + ?ABORT(Message, []) + end}; +expand_sh_flag(abort_on_error) -> + {error_handler, + fun(Command, Rc) -> + ?ABORT("~s failed with error: ~w\n", [Command, Rc]) + end}; +expand_sh_flag(use_stdout) -> + {output_handler, + fun(Line, Acc) -> + ?CONSOLE("~s", [Line]), + [Acc | Line] + end}; +expand_sh_flag({use_stdout, false}) -> + {output_handler, + fun(Line, Acc) -> + [Acc | Line] + end}; +expand_sh_flag({cd, Dir}) -> + {port_settings, {cd, Dir}}; +expand_sh_flag({env, Env}) -> + {port_settings, {env, Env}}. + +sh_loop(Port, Fun, Acc) -> receive {Port, {data, {_, "_port_cmd_status_ " ++ Status}}} -> (catch erlang:port_close(Port)), % sigh () for indentation case list_to_integer(Status) of - 0 -> ok; + 0 -> {ok, lists:flatten(Acc)}; Rc -> {error, Rc} end; - {Port, {data, {_, Line}}} -> - ?CONSOLE("~s\n", [Line]), - sh_loop(Port); + {Port, {data, {eol, Line}}} -> + sh_loop(Port, Fun, Fun(Line ++ "\n", Acc)); + {Port, {data, {noeol, Line}}} -> + sh_loop(Port, Fun, Fun(Line, Acc)); {Port, {exit_status, 0}} -> - ok; + {ok, lists:flatten(Acc)}; {Port, {exit_status, Rc}} -> {error, Rc} end. diff --git a/test/rebar_file_utils_tests.erl b/test/rebar_file_utils_tests.erl index 6b87986..fd9a141 100644 --- a/test/rebar_file_utils_tests.erl +++ b/test/rebar_file_utils_tests.erl @@ -215,6 +215,18 @@ cp_r_overwrite_dir_fail_test_() -> [filename:join([?TMP_DIR,"source"])], filename:join([?TMP_DIR,"dest"])))]}. +mv_file_test_() -> + {"move a file to folder", + setup, + fun() -> + setup(), + rebar_file_utils:mv(filename:join([?TMP_DIR,"source","file1"]), + filename:join([?TMP_DIR,"dest"])) + end, + fun teardown/1, + [?_assert(filelib:is_file(filename:join([?TMP_DIR,"dest","file1"]))), + ?_assertNot(filelib:is_file(filename:join([?TMP_DIR,"source","file1"])))]}. + %% ==================================================================== %% Utilities %% ==================================================================== -- cgit v1.1 From 9441251f9fa7e214a35abd1b4d4eef85d4dc35c3 Mon Sep 17 00:00:00 2001 From: Juhani Rankimies Date: Sun, 26 Dec 2010 13:56:17 +0100 Subject: Use file:change_mode/2 instead of invoking chmod --- src/rebar_escripter.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rebar_escripter.erl b/src/rebar_escripter.erl index f2870d3..20f5e66 100644 --- a/src/rebar_escripter.erl +++ b/src/rebar_escripter.erl @@ -30,6 +30,7 @@ clean/2]). -include("rebar.hrl"). +-include_lib("kernel/include/file.hrl"). %% =================================================================== %% Public API @@ -70,7 +71,8 @@ escriptize(Config, AppFile) -> end, %% Finally, update executable perms for our script - [] = os:cmd(?FMT("chmod u+x ~p", [Filename])), + {ok, #file_info{mode = Mode}} = file:read_file_info(Filename), + ok = file:change_mode(Filename, Mode bor 8#00100), ok. clean(Config, AppFile) -> -- cgit v1.1 From 422beee324e24d5db404b9f61d26cceb73a9fcce Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Thu, 6 Jan 2011 14:51:35 +0100 Subject: Return more descriptive dependency errors --- src/rebar_deps.erl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl index ded75db..72d982a 100644 --- a/src/rebar_deps.erl +++ b/src/rebar_deps.erl @@ -247,16 +247,19 @@ is_app_available(App, VsnRegex, Path) -> nomatch -> ?WARN("~s has version ~p; requested regex was ~s\n", [AppFile, Vsn, VsnRegex]), - {false, version_mismatch} + {false, {version_mismatch, + {AppFile, + {expected, VsnRegex}, {has, Vsn}}}} end; OtherApp -> ?WARN("~s has application id ~p; expected ~p\n", [AppFile, OtherApp, App]), - {false, name_mismatch} + {false, {name_mismatch, + {AppFile, {expected, App}, {has, OtherApp}}}} end; false -> ?WARN("Expected ~s to be an app dir (containing ebin/*.app), but no .app found.\n", [Path]), - {false, missing_app_file} + {false, {missing_app_file, Path}} end. use_source(Dep) -> @@ -280,7 +283,7 @@ use_source(Dep, Count) -> %% The app that was downloaded doesn't match up (or had %% errors or something). For the time being, abort. ?ABORT("Dependency dir ~s failed application validation " - "with reason ~p.\n", [Dep#dep.dir, Reason]) + "with reason:~n~p.\n", [Dep#dep.dir, Reason]) end; false -> ?CONSOLE("Pulling ~p from ~p\n", [Dep#dep.app, Dep#dep.source]), -- cgit v1.1 From 46b2c0612e893a5bf34ec720810a9bd52928fd63 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 7 Jan 2011 12:40:02 +0100 Subject: Fix bug 770 --- src/rebar_app_utils.erl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl index 9574775..ea8e079 100644 --- a/src/rebar_app_utils.erl +++ b/src/rebar_app_utils.erl @@ -80,7 +80,7 @@ app_name(AppFile) -> app_applications(AppFile) -> case load_app_file(AppFile) of {ok, _, AppInfo} -> - proplists:get_value(applications, AppInfo); + get_value(applications, AppInfo, AppFile); {error, Reason} -> ?ABORT("Failed to extract applications from ~s: ~p\n", [AppFile, Reason]) @@ -89,7 +89,7 @@ app_applications(AppFile) -> app_vsn(AppFile) -> case load_app_file(AppFile) of {ok, _, AppInfo} -> - proplists:get_value(vsn, AppInfo); + get_value(vsn, AppInfo, AppFile); {error, Reason} -> ?ABORT("Failed to extract vsn from ~s: ~p\n", [AppFile, Reason]) @@ -116,3 +116,11 @@ load_app_file(Filename) -> {AppName, AppData} -> {ok, AppName, AppData} end. + +get_value(Key, AppInfo, AppFile) -> + case proplists:get_value(Key, AppInfo) of + undefined -> + ?ABORT("Failed to get app value '~p' from '~s'~n", [Key, AppFile]); + Value -> + Value + end. -- cgit v1.1 From 220eec71f6f83e611dad1238c5f5b47d6ef99c22 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sat, 8 Jan 2011 19:47:17 +0100 Subject: Remove unused fun rebar_utils:get_os/0 --- src/rebar_utils.erl | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index ae27455..7dbb8f7 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -29,7 +29,6 @@ -export([get_cwd/0, is_arch/1, get_arch/0, - get_os/0, sh/2, find_files/2, now_str/0, @@ -63,15 +62,6 @@ get_arch() -> Words = integer_to_list(8 * erlang:system_info(wordsize)), erlang:system_info(system_architecture) ++ "-" ++ Words. -get_os() -> - Arch = erlang:system_info(system_architecture), - case match_first([{"linux", linux}, {"darwin", darwin}], Arch) of - nomatch -> - {unknown, Arch}; - ArchAtom -> - ArchAtom - end. - %% %% Options = [Option] -- defaults to [use_stdout, abort_on_error] %% Option = ErrorOption | OutputOption | {cd, string()} | {env, Env} @@ -164,16 +154,6 @@ find_executable(Name) -> %% Internal functions %% ==================================================================== -match_first([], _Val) -> - nomatch; -match_first([{Regex, MatchValue} | Rest], Val) -> - case re:run(Val, Regex, [{capture, none}]) of - match -> - MatchValue; - nomatch -> - match_first(Rest, Val) - end. - expand_sh_flag(return_on_error) -> {error_handler, fun(_Command, Rc) -> -- cgit v1.1 From 5a371496422a60b6ce6d409d680ea9107eefb019 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 7 Jan 2011 12:48:22 +0100 Subject: Fix Dialyzer warning --- src/rebar_utils.erl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 7dbb8f7..17fb95a 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -166,9 +166,7 @@ expand_sh_flag({abort_on_error, Message}) -> end}; expand_sh_flag(abort_on_error) -> {error_handler, - fun(Command, Rc) -> - ?ABORT("~s failed with error: ~w\n", [Command, Rc]) - end}; + fun log_and_abort/2}; expand_sh_flag(use_stdout) -> {output_handler, fun(Line, Acc) -> @@ -185,6 +183,10 @@ expand_sh_flag({cd, Dir}) -> expand_sh_flag({env, Env}) -> {port_settings, {env, Env}}. +-spec log_and_abort(string(), integer()) -> no_return(). +log_and_abort(Command, Rc) -> + ?ABORT("~s failed with error: ~w\n", [Command, Rc]). + sh_loop(Port, Fun, Acc) -> receive {Port, {data, {_, "_port_cmd_status_ " ++ Status}}} -> -- cgit v1.1 From 5b05e54cda77d6e45fd6d1cc8ea1dabfafa6bcb1 Mon Sep 17 00:00:00 2001 From: Joseph Wayne Norton Date: Sun, 9 Jan 2011 16:06:51 +0100 Subject: Add otp_release to platform string --- rebar.config.sample | 3 ++- src/rebar_erlc_compiler.erl | 25 +++++++++++++++++++------ src/rebar_utils.erl | 3 ++- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/rebar.config.sample b/rebar.config.sample index f963c30..ea3fdc4 100644 --- a/rebar.config.sample +++ b/rebar.config.sample @@ -31,7 +31,8 @@ {erl_opts, [{i, "myinclude"}, {src_dirs, ["src1", "src2"]}, {platform_define, "(linux|solaris|freebsd|darwin)", 'HAVE_SENDFILE'}, - {platform_define, "(linux|freebsd)", 'BACKLOG', 128}]}. + {platform_define, "(linux|freebsd)", 'BACKLOG', 128}, + {platform_define, "R13", 'old_inets'}]}. %% MIB Options? {mib_opts, []}. diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 871b9a1..f533d48 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -42,16 +42,29 @@ %% %% * erl_opts - Erlang list of options passed to compile:file/2 %% It is also possible to specify platform specific -%% options by specifying a triplet where the first string -%% is a regex that is checked against Erlang's system -%% architecture string. E.g. to define HAVE_SENDFILE only -%% on systems with sendfile() and define BACKLOG on -%% Linux/FreeBSD as 128 do: +%% options by specifying a pair or a triplet where the +%% first string is a regex that is checked against the +%% string +%% +%% OtpRelease ++ "-" ++ SysArch ++ "-" ++ Words. +%% +%% where +%% +%% OtpRelease = erlang:system_info(otp_release). +%% SysArch = erlang:system_info(system_architecture). +%% Words = integer_to_list(8 * erlang:system_info(wordsize)). +%% +%% E.g. to define HAVE_SENDFILE only on systems with +%% sendfile(), to define BACKLOG on Linux/FreeBSD as 128, +%% and to define 'old_inets' for R13 OTP release do: +%% %% {erl_opts, [{platform_define, %% "(linux|solaris|freebsd|darwin)", %% 'HAVE_SENDFILE'}, %% {platform_define, "(linux|freebsd)", -%% 'BACKLOG', 128}]}. +%% 'BACKLOG', 128}, +%% {platform_define, "R13", +%% 'old_inets'}]}. %% -spec compile(Config::#config{}, AppFile::string()) -> 'ok'. diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 17fb95a..f49969a 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -60,7 +60,8 @@ is_arch(ArchRegex) -> get_arch() -> Words = integer_to_list(8 * erlang:system_info(wordsize)), - erlang:system_info(system_architecture) ++ "-" ++ Words. + erlang:system_info(otp_release) ++ "-" + ++ erlang:system_info(system_architecture) ++ "-" ++ Words. %% %% Options = [Option] -- defaults to [use_stdout, abort_on_error] -- cgit v1.1 From 7b0d970646eb45079d1ba8f4d50996b42b7ddbca Mon Sep 17 00:00:00 2001 From: Juhani Rankimies Date: Wed, 12 Jan 2011 17:58:10 +0200 Subject: Set local scope for env vars in rebar.bat --- rebar.bat | 1 + 1 file changed, 1 insertion(+) diff --git a/rebar.bat b/rebar.bat index 5ac634b..547da6b 100644 --- a/rebar.bat +++ b/rebar.bat @@ -1,3 +1,4 @@ @echo off +setlocal set rebarscript=%0 escript.exe %rebarscript:.bat=% %* -- cgit v1.1 From 84f6d0bed032f2a2c8e6a0522361f048649c73c3 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Thu, 13 Jan 2011 16:04:56 +0100 Subject: Add README and update existing docs --- HACKING | 50 ----------------------------------- README.md | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TODO | 2 -- 3 files changed, 91 insertions(+), 52 deletions(-) delete mode 100644 HACKING create mode 100644 README.md delete mode 100644 TODO diff --git a/HACKING b/HACKING deleted file mode 100644 index 6df34c5..0000000 --- a/HACKING +++ /dev/null @@ -1,50 +0,0 @@ -Indenting -========= -To have consistent indenting we have vi modeline/emacs local variable -headers in rebar's source files. This works automatically with vi. -With Emacs you have to declare 'erlang-indent-level set to 4' -as a safe local variable value. If not configured Emacs will prompt -you to save this as part of custom-set-variables: - '(safe-local-variable-values (quote ((erlang-indent-level . 4)))) -You can also tell Emacs to ignore file variables: -(setq enable-local-variables nil - enable-local-eval nil) - - -Writing Commit Messages -======================= - - One line summary (< 50 characters) - - Longer description (wrap at 72 characters) - -Summary -------- - -* Less than 50 characters - -* What was changed - -* Imperative present tense (fix, add, change) - - Fix bug 42 - Add 'foobar' command - Change default timeout to 42 - -* No period - -Description ------------ - -* Wrap at 72 characters - -* Why, explain intention and implementation approach - -* Present tense - -Atomicity ---------- - -* Break up logical changes - -* Make whitespace changes separately diff --git a/README.md b/README.md new file mode 100644 index 0000000..7145bbd --- /dev/null +++ b/README.md @@ -0,0 +1,91 @@ +rebar +===== + +rebar is an Erlang build tool that makes it easy to compile and +test Erlang applications, port drivers and releases. + +rebar is a self-contained Erlang script, so it's easy to distribute or even +embed directly in a project. Where possible, rebar uses standard Erlang/OTP +conventions for project structures, thus minimizing the amount of build +configuration work. rebar also provides dependency management, enabling +application writers to easily re-use common libraries from a variety of +locations (git, hg, etc). + +Building +-------- + +Information on building and installing Erlang/OTP can be found +in the `INSTALL.md` document. + +### Dependencies + +To build rebar you will need a working installation of Erlang R13B03 (or +later). + +Should you want to clone the rebar repository, you will also require git. + +#### Downloading + +Clone the git repository: + + $ git clone git://github.com/basho/rebar.git + +#### Building rebar + + $ cd rebar/ + $ ./bootstrap + Recompile: src/getopt + ... + Recompile: src/rebar_utils + ==> rebar (compile) + Congratulations! You now have a self-contained script called "rebar" in + your current working directory. Place this script anywhere in your path + and you can use rebar to build OTP-compliant apps. + + +Contributing to rebar +===================== + +Indentation +----------- + +To have consistent indentation we have vi modeline/emacs local variable +headers in rebar's source files. This works automatically with vi. +With Emacs you have to declare 'erlang-indent-level +set to 4 +as a safe local variable value. If not configured Emacs will prompt +you to save this as part of custom-set-variables: + + '(safe-local-variable-values (quote ((erlang-indent-level . 4)))) +You can also tell Emacs to ignore file variables: + + (setq enable-local-variables nil + enable-local-eval nil) + + +Writing Commit Messages +----------------------- + +One line summary (< 50 characters) +Longer description (wrap at 72 characters) + +### Summary + +* Less than 50 characters +* What was changed +* Imperative present tense (fix, add, change) +> Fix bug 123 +> Add 'foobar' command +> Change default timeout to 123 +* No period + +### Description + +* Wrap at 72 characters +* Why, explain intention and implementation approach +* Present tense + +### Atomicity + +* Break up logical changes +* Make whitespace changes separately diff --git a/TODO b/TODO deleted file mode 100644 index f921ce0..0000000 --- a/TODO +++ /dev/null @@ -1,2 +0,0 @@ -* write documentation -* ZSH completion script -- cgit v1.1 From 6d6fbacddb88f5c664790c9d6e355cedaf435314 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Thu, 13 Jan 2011 16:07:16 +0100 Subject: Update README formatting --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7145bbd..2050202 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ rebar ===== -rebar is an Erlang build tool that makes it easy to compile and +rebar is an Erlang build tool that makes it easy to compile and test Erlang applications, port drivers and releases. -rebar is a self-contained Erlang script, so it's easy to distribute or even -embed directly in a project. Where possible, rebar uses standard Erlang/OTP -conventions for project structures, thus minimizing the amount of build -configuration work. rebar also provides dependency management, enabling -application writers to easily re-use common libraries from a variety of +rebar is a self-contained Erlang script, so it's easy to distribute or even +embed directly in a project. Where possible, rebar uses standard Erlang/OTP +conventions for project structures, thus minimizing the amount of build +configuration work. rebar also provides dependency management, enabling +application writers to easily re-use common libraries from a variety of locations (git, hg, etc). Building -- cgit v1.1 From 1f1793cc5e747c9a937d1f304f8a99f9316f2672 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Thu, 13 Jan 2011 16:26:14 +0100 Subject: Update README: Dialyzer and Tidier --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index 2050202..16f4541 100644 --- a/README.md +++ b/README.md @@ -89,3 +89,25 @@ Longer description (wrap at 72 characters) * Break up logical changes * Make whitespace changes separately + +Dialyzer and Tidier +------------------- + +Before you submit a patch check for discrepancies with +[Dialyzer](http://www.erlang.org/doc/man/dialyzer.html): + +
+$ cd rebar/
+$ ./bootstrap debug
+$ dialyzer ebin -Wunmatched_returns -Werror_handling -Wrace_conditions -Wunderspecs
+
+ +It is **strongly recommended** to check the code with +[Tidier](http://tidier.softlab.ntua.gr:20000/tidier/getstarted). +Select all transformation options and enable **automatic** +transformation. +If Tidier suggests a transformation apply the changes **manually** +to the source code. +Do not use the code from the tarball (*out.tgz*) as it will have +white-space changes +applied by Erlang's pretty-printer. -- cgit v1.1 From a8870807fc6e677b471591ba9313179a5c6c78b6 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 7 Jan 2011 14:58:30 +0100 Subject: Fix code clarity --- src/rebar_config.erl | 33 ++++++++++++++++++--------------- src/rebar_core.erl | 5 +++-- src/rebar_templater.erl | 6 +++--- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/rebar_config.erl b/src/rebar_config.erl index cba0e64..7da6900 100644 --- a/src/rebar_config.erl +++ b/src/rebar_config.erl @@ -58,20 +58,23 @@ new(ParentConfig) -> %% Load terms from rebar.config, if it exists Dir = rebar_utils:get_cwd(), ConfigFile = filename:join([Dir, ConfName]), - case file:consult(ConfigFile) of - {ok, Terms} -> - %% Found a config file with some terms. We need to be able to - %% distinguish between local definitions (i.e. from the file - %% in the cwd) and inherited definitions. To accomplish this, - %% we use a marker in the proplist (since order matters) between - %% the new and old defs. - Opts = Terms ++ [local] ++ [Opt || Opt <- ParentConfig#config.opts, Opt /= local]; - {error, enoent} -> - Opts = [local] ++ [Opt || Opt <- ParentConfig#config.opts, Opt /= local]; - Other -> - Opts = undefined, % Keep erlc happy - ?ABORT("Failed to load ~s: ~p\n", [ConfigFile, Other]) - end, + Opts = case file:consult(ConfigFile) of + {ok, Terms} -> + %% Found a config file with some terms. We need to + %% be able to distinguish between local definitions + %% (i.e. from the file in the cwd) and inherited + %% definitions. To accomplish this, we use a marker + %% in the proplist (since order matters) between + %% the new and old defs. + Terms ++ [local] ++ + [Opt || Opt <- ParentConfig#config.opts, Opt /= local]; + {error, enoent} -> + [local] ++ + [Opt || Opt <- ParentConfig#config.opts, Opt /= local]; + Other -> + ?ABORT("Failed to load ~s: ~p\n", [ConfigFile, Other]) + end, + #config { dir = Dir, opts = Opts }. get(Config, Key, Default) -> @@ -91,7 +94,7 @@ set(Config, Key, Value) -> Config#config { opts = [{Key, Value} | Opts] }. set_global(jobs=Key, Value) when is_list(Value) -> - set_global(Key,list_to_integer(Value)); + set_global(Key, list_to_integer(Value)); set_global(jobs=Key, Value) when is_integer(Value) -> application:set_env(rebar_global, Key, erlang:max(1,Value)); set_global(Key, Value) -> diff --git a/src/rebar_core.erl b/src/rebar_core.erl index e8b4e57..f8eb6f5 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -453,10 +453,11 @@ execute(Command, Modules, Config, ModuleFile) -> ?FAIL; {Module, {error, _} = Other} -> ?ABORT("~p failed while processing ~s in module ~s: ~s\n", - [Command, Dir, Module, io_lib:print(Other, 1,80,-1)]); + [Command, Dir, Module, + io_lib:print(Other, 1, 80, -1)]); Other -> ?ABORT("~p failed while processing ~s: ~s\n", - [Command, Dir, io_lib:print(Other, 1,80,-1)]) + [Command, Dir, io_lib:print(Other, 1, 80, -1)]) end end. diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl index e251f40..b241fd5 100644 --- a/src/rebar_templater.erl +++ b/src/rebar_templater.erl @@ -263,8 +263,8 @@ write_file(Output, Data, Force) -> %% perform the function if we're allowed, %% otherwise just process the next template - if - Force =:= "1"; FileExists =:= false -> + case Force =:= "1" orelse FileExists =:= false of + true -> ok = filelib:ensure_dir(Output), if {Force, FileExists} =:= {"1", true} -> @@ -280,7 +280,7 @@ write_file(Output, Data, Force) -> ?ABORT("Failed to write output file ~p: ~p\n", [Output, Reason]) end; - true -> + false -> {error, exists} end. -- cgit v1.1 From 58fd80917a2fab2353bc19f9f4bc648d8e54db92 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 7 Jan 2011 16:32:36 +0100 Subject: Fix file existence checks --- src/rebar_erlydtl_compiler.erl | 2 +- src/rebar_eunit.erl | 2 +- src/rebar_neotoma_compiler.erl | 2 +- src/rebar_rel_utils.erl | 2 +- src/rebar_templater.erl | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rebar_erlydtl_compiler.erl b/src/rebar_erlydtl_compiler.erl index 6b2160c..b746642 100644 --- a/src/rebar_erlydtl_compiler.erl +++ b/src/rebar_erlydtl_compiler.erl @@ -174,7 +174,7 @@ referenced_dtls1(Step, Config, Seen) -> end, Step)), DocRoot = option(doc_root, DtlOpts), WithPaths = [ filename:join([DocRoot, F]) || F <- AllRefs ], - Existing = [F || F <- WithPaths, filelib:is_file(F)], + Existing = [F || F <- WithPaths, filelib:is_regular(F)], New = sets:subtract(sets:from_list(Existing), Seen), case sets:size(New) of 0 -> Seen; diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl index 1341f9d..f1ddead 100644 --- a/src/rebar_eunit.erl +++ b/src/rebar_eunit.erl @@ -195,7 +195,7 @@ is_quickcheck_avail() -> {error, bad_name} -> IsAvail = false; Dir -> - IsAvail = filelib:is_file(filename:join(Dir, "eqc.hrl")) + IsAvail = filelib:is_regular(filename:join(Dir, "eqc.hrl")) end, erlang:put(is_quickcheck_avail, IsAvail), ?DEBUG("Quickcheck availability: ~p\n", [IsAvail]), diff --git a/src/rebar_neotoma_compiler.erl b/src/rebar_neotoma_compiler.erl index c2e6f0d..ce7a0d3 100644 --- a/src/rebar_neotoma_compiler.erl +++ b/src/rebar_neotoma_compiler.erl @@ -133,7 +133,7 @@ referenced_pegs1(Step, Config, Seen) -> end, Step)), DocRoot = option(doc_root, NeoOpts), WithPaths = [ filename:join([DocRoot, F]) || F <- AllRefs ], - Existing = [F || F <- WithPaths, filelib:is_file(F)], + Existing = [F || F <- WithPaths, filelib:is_regular(F)], New = sets:subtract(sets:from_list(Existing), Seen), case sets:size(New) of 0 -> Seen; diff --git a/src/rebar_rel_utils.erl b/src/rebar_rel_utils.erl index b955a53..978f9d6 100644 --- a/src/rebar_rel_utils.erl +++ b/src/rebar_rel_utils.erl @@ -33,7 +33,7 @@ is_rel_dir() -> is_rel_dir(Dir) -> Fname = filename:join([Dir, "reltool.config"]), - case filelib:is_file(Fname) of + case filelib:is_regular(Fname) of true -> {true, Fname}; false -> diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl index b241fd5..748c8b6 100644 --- a/src/rebar_templater.erl +++ b/src/rebar_templater.erl @@ -259,7 +259,7 @@ render(Bin, Context) -> write_file(Output, Data, Force) -> %% determine if the target file already exists - FileExists = filelib:is_file(Output), + FileExists = filelib:is_regular(Output), %% perform the function if we're allowed, %% otherwise just process the next template -- cgit v1.1 From d922985b368cebfa10606f347d84eafb06c26d15 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 7 Jan 2011 17:24:27 +0100 Subject: Fix typos --- src/rebar_core.erl | 4 ++-- src/rebar_xref.erl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rebar_core.erl b/src/rebar_core.erl index f8eb6f5..353a218 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -476,8 +476,8 @@ update_code_path(Config) -> restore_code_path(no_change) -> ok; restore_code_path({old, Path}) -> - %% Verify that all of the paths still exist -- some dynamically add paths - %% can get blown away during clean. + %% Verify that all of the paths still exist -- some dynamically + %% added paths can get blown away during clean. true = code:set_path([F || F <- Path, filelib:is_file(F)]), ok. diff --git a/src/rebar_xref.erl b/src/rebar_xref.erl index 55b4f0e..0e29792 100644 --- a/src/rebar_xref.erl +++ b/src/rebar_xref.erl @@ -111,7 +111,7 @@ filter_away_ignored(UnusedExports) -> %% Functions can be ignored by using %% -ignore_xref([{F, A}, ...]). - %% Setup a filter function that build a list of behaviour callbacks and/or + %% Setup a filter function that builds a list of behaviour callbacks and/or %% any functions marked to ignore. We then use this list to mask any functions %% marked as unused exports by xref F = fun(Mod) -> -- cgit v1.1 From e4036cbe56de29be1a4773d459c87700884f17d0 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sat, 8 Jan 2011 19:09:24 +0100 Subject: Apply Tidier suggestions --- src/getopt.erl | 22 +++++++++++----------- src/rebar_ct.erl | 2 +- src/rebar_deps.erl | 15 +++++++++------ src/rebar_dialyzer.erl | 2 +- src/rebar_erlydtl_compiler.erl | 15 +++++++-------- src/rebar_file_utils.erl | 32 ++++++++++++++++---------------- src/rebar_neotoma_compiler.erl | 19 +++++++++---------- src/rebar_port_compiler.erl | 5 ++++- src/rebar_reltool.erl | 14 ++++++++------ src/rebar_require_vsn.erl | 5 +++-- src/rebar_utils.erl | 16 ++++++++-------- test/rebar_eunit_tests.erl | 2 +- 12 files changed, 78 insertions(+), 71 deletions(-) diff --git a/src/getopt.erl b/src/getopt.erl index bb7fae2..5f9fe61 100644 --- a/src/getopt.erl +++ b/src/getopt.erl @@ -75,10 +75,10 @@ parse(OptSpecList, OptAcc, ArgAcc, _ArgPos, ["--" | Tail]) -> % Any argument present after the terminator is not considered an option. {ok, {lists:reverse(append_default_options(OptSpecList, OptAcc)), lists:reverse(ArgAcc, Tail)}}; %% Process long options. -parse(OptSpecList, OptAcc, ArgAcc, ArgPos, [[$-, $- | OptArg] = OptStr | Tail]) -> +parse(OptSpecList, OptAcc, ArgAcc, ArgPos, ["--" ++ OptArg = OptStr | Tail]) -> parse_option_long(OptSpecList, OptAcc, ArgAcc, ArgPos, Tail, OptStr, OptArg); %% Process short options. -parse(OptSpecList, OptAcc, ArgAcc, ArgPos, [[$- | [_Char | _] = OptArg] = OptStr | Tail]) -> +parse(OptSpecList, OptAcc, ArgAcc, ArgPos, ["-" ++ ([_Char | _] = OptArg) = OptStr | Tail]) -> parse_option_short(OptSpecList, OptAcc, ArgAcc, ArgPos, Tail, OptStr, OptArg); %% Process non-option arguments. parse(OptSpecList, OptAcc, ArgAcc, ArgPos, [Arg | Tail]) -> @@ -111,11 +111,11 @@ parse_option_long(OptSpecList, OptAcc, ArgAcc, ArgPos, Args, OptStr, OptArg) -> parse_option_assigned_arg(OptSpecList, OptAcc, ArgAcc, ArgPos, Args, OptStr, Long, Arg); Long -> - case lists:keysearch(Long, ?OPT_LONG, OptSpecList) of - {value, {Name, _Short, Long, undefined, _Help}} -> + case lists:keyfind(Long, ?OPT_LONG, OptSpecList) of + {Name, _Short, Long, undefined, _Help} -> parse(OptSpecList, [Name | OptAcc], ArgAcc, ArgPos, Args); - {value, {_Name, _Short, Long, _ArgSpec, _Help} = OptSpec} -> + {_Name, _Short, Long, _ArgSpec, _Help} = OptSpec -> % The option argument string is empty, but the option requires % an argument, so we look into the next string in the list. parse_option_next_arg(OptSpecList, OptAcc, ArgAcc, ArgPos, Args, OptSpec); @@ -132,8 +132,8 @@ parse_option_long(OptSpecList, OptAcc, ArgAcc, ArgPos, Args, OptStr, OptArg) -> [string()], string(), string(), string()) -> {ok, {[option()], [string()]}}. parse_option_assigned_arg(OptSpecList, OptAcc, ArgAcc, ArgPos, Args, OptStr, Long, Arg) -> - case lists:keysearch(Long, ?OPT_LONG, OptSpecList) of - {value, {_Name, _Short, Long, ArgSpec, _Help} = OptSpec} -> + case lists:keyfind(Long, ?OPT_LONG, OptSpecList) of + {_Name, _Short, Long, ArgSpec, _Help} = OptSpec -> case ArgSpec of undefined -> throw({error, {invalid_option_arg, OptStr}}); @@ -151,7 +151,7 @@ parse_option_assigned_arg(OptSpecList, OptAcc, ArgAcc, ArgPos, Args, OptStr, Lon split_assigned_arg(OptStr) -> split_assigned_arg(OptStr, OptStr, []). -split_assigned_arg(_OptStr, [$= | Tail], Acc) -> +split_assigned_arg(_OptStr, "=" ++ Tail, Acc) -> {lists:reverse(Acc), Tail}; split_assigned_arg(OptStr, [Char | Tail], Acc) -> split_assigned_arg(OptStr, Tail, [Char | Acc]); @@ -170,11 +170,11 @@ split_assigned_arg(OptStr, [], _Acc) -> -spec parse_option_short([option_spec()], [option()], [string()], integer(), [string()], string(), string()) -> {ok, {[option()], [string()]}}. parse_option_short(OptSpecList, OptAcc, ArgAcc, ArgPos, Args, OptStr, [Short | Arg]) -> - case lists:keysearch(Short, ?OPT_SHORT, OptSpecList) of - {value, {Name, Short, _Long, undefined, _Help}} -> + case lists:keyfind(Short, ?OPT_SHORT, OptSpecList) of + {Name, Short, _Long, undefined, _Help} -> parse_option_short(OptSpecList, [Name | OptAcc], ArgAcc, ArgPos, Args, OptStr, Arg); - {value, {_Name, Short, _Long, ArgSpec, _Help} = OptSpec} -> + {_Name, Short, _Long, ArgSpec, _Help} = OptSpec -> case Arg of [] -> % The option argument string is empty, but the option requires diff --git a/src/rebar_ct.erl b/src/rebar_ct.erl index d6d4675..0c8e2ef 100644 --- a/src/rebar_ct.erl +++ b/src/rebar_ct.erl @@ -137,7 +137,7 @@ make_cmd(TestDir, Config) -> %% that are part of the root Erlang install are filtered out to %% avoid duplication R = code:root_dir(), - NonLibCodeDirs = [P || P <- code:get_path(), lists:prefix(R, P) == false], + NonLibCodeDirs = [P || P <- code:get_path(), not lists:prefix(R, P)], CodeDirs = [io_lib:format("\"~s\"", [Dir]) || Dir <- [EbinDir|NonLibCodeDirs]], CodePathString = string:join(CodeDirs, " "), diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl index 72d982a..d93b158 100644 --- a/src/rebar_deps.erl +++ b/src/rebar_deps.erl @@ -134,8 +134,9 @@ compile(Config, AppFile) -> DepsDir = get_deps_dir(), Deps = rebar_config:get_local(Config, deps, []), {AvailableDeps, _} = find_deps(find, Deps), - _ = [delete_dep(D) || D <- AvailableDeps, - lists:prefix(DepsDir, D#dep.dir) == true], + _ = [delete_dep(D) + || D <- AvailableDeps, + lists:prefix(DepsDir, D#dep.dir)], ok. @@ -339,11 +340,13 @@ update_source(Dep) -> end. update_source(AppDir, {git, _Url, {branch, Branch}}) -> - rebar_utils:sh("git fetch origin", [{cd, AppDir}]), - rebar_utils:sh(?FMT("git checkout -q origin/~s", [Branch]), [{cd, AppDir}]); + ShOpts = [{cd, AppDir}], + rebar_utils:sh("git fetch origin", ShOpts), + rebar_utils:sh(?FMT("git checkout -q origin/~s", [Branch]), ShOpts); update_source(AppDir, {git, _Url, {tag, Tag}}) -> - rebar_utils:sh("git fetch --tags origin", [{cd, AppDir}]), - rebar_utils:sh(?FMT("git checkout -q ~s", [Tag]), [{cd, AppDir}]); + ShOpts = [{cd, AppDir}], + rebar_utils:sh("git fetch --tags origin", ShOpts), + rebar_utils:sh(?FMT("git checkout -q ~s", [Tag]), ShOpts); update_source(AppDir, {git, Url, Refspec}) -> update_source(AppDir, {git, Url, {branch, Refspec}}); update_source(AppDir, {svn, _Url, Rev}) -> diff --git a/src/rebar_dialyzer.erl b/src/rebar_dialyzer.erl index 9d45445..acaf69a 100644 --- a/src/rebar_dialyzer.erl +++ b/src/rebar_dialyzer.erl @@ -193,7 +193,7 @@ existing_plt_path(Config, File) -> ?ABORT("No PLT found~n", []) end end; - [$~|[$/|Plt]] -> + "~/" ++ Plt -> filename:join(Home,Plt); Plt -> Plt diff --git a/src/rebar_erlydtl_compiler.erl b/src/rebar_erlydtl_compiler.erl index b746642..d30b56c 100644 --- a/src/rebar_erlydtl_compiler.erl +++ b/src/rebar_erlydtl_compiler.erl @@ -164,14 +164,13 @@ referenced_dtls1(Step, Config, Seen) -> [{return, list}]), AllRefs = lists:append( - lists:map( - fun(F) -> - {ok, Res} = rebar_utils:sh( - lists:flatten(["grep -o [^\\\"]*", - ExtMatch," ",F]), - [{use_stdout, false}]), - string:tokens(Res, "\n") - end, Step)), + [begin + {ok, Res} = rebar_utils:sh( + lists:flatten(["grep -o [^\\\"]*", + ExtMatch," ",F]), + [{use_stdout, false}]), + string:tokens(Res, "\n") + end || F <- Step]), DocRoot = option(doc_root, DtlOpts), WithPaths = [ filename:join([DocRoot, F]) || F <- AllRefs ], Existing = [F || F <- WithPaths, filelib:is_regular(F)], diff --git a/src/rebar_file_utils.erl b/src/rebar_file_utils.erl index 0a7cd4c..026b06b 100644 --- a/src/rebar_file_utils.erl +++ b/src/rebar_file_utils.erl @@ -49,8 +49,8 @@ rm_rf(Target) -> ok; {win32, _} -> Filelist = filelib:wildcard(Target), - Dirs = lists:filter(fun filelib:is_dir/1,Filelist), - Files = lists:subtract(Filelist,Dirs), + Dirs = [F || F <- Filelist, filelib:is_dir(F)], + Files = Filelist -- Dirs, ok = delete_each(Files), ok = delete_each_dir_win32(Dirs), ok @@ -82,9 +82,10 @@ mv(Source, Dest) -> [filename:nativename(Source), filename:nativename(Dest)]), [{use_stdout, false}, return_on_error]), - case length(R) == 0 of - true -> ok; - false -> + case R of + [] -> + ok; + _ -> {error, lists:flatten( io_lib:format("Failed to move ~s to ~s~n", [Source, Dest]))} @@ -130,25 +131,24 @@ xcopy_win32(Source,Dest)-> [Source, Dest]))} end. -cp_r_win32({true,SourceDir},{true,DestDir}) -> +cp_r_win32({true, SourceDir}, {true, DestDir}) -> % from directory to directory SourceBase = filename:basename(SourceDir), - ok = case file:make_dir(filename:join(DestDir,SourceBase)) of - {error,eexist} -> ok; + ok = case file:make_dir(filename:join(DestDir, SourceBase)) of + {error, eexist} -> ok; Other -> Other end, - ok = xcopy_win32(SourceDir,filename:join(DestDir,SourceBase)); -cp_r_win32({false,Source},{true,DestDir}) -> + ok = xcopy_win32(SourceDir, filename:join(DestDir, SourceBase)); +cp_r_win32({false, Source} = S,{true, DestDir}) -> % from file to directory - cp_r_win32({false,Source}, - {false,filename:join(DestDir,filename:basename(Source))}); -cp_r_win32({false,Source},{false,Dest}) -> + cp_r_win32(S, {false, filename:join(DestDir, filename:basename(Source))}); +cp_r_win32({false, Source},{false, Dest}) -> % from file to file - {ok,_} = file:copy(Source,Dest), + {ok,_} = file:copy(Source, Dest), ok; cp_r_win32(Source,Dest) -> - Dst = {filelib:is_dir(Dest),Dest}, + Dst = {filelib:is_dir(Dest), Dest}, lists:foreach(fun(Src) -> - ok = cp_r_win32({filelib:is_dir(Src),Src},Dst) + ok = cp_r_win32({filelib:is_dir(Src), Src}, Dst) end, filelib:wildcard(Source)), ok. diff --git a/src/rebar_neotoma_compiler.erl b/src/rebar_neotoma_compiler.erl index ce7a0d3..e67007c 100644 --- a/src/rebar_neotoma_compiler.erl +++ b/src/rebar_neotoma_compiler.erl @@ -121,16 +121,15 @@ referenced_pegs1(Step, Config, Seen) -> NeoOpts = neotoma_opts(Config), ExtMatch = re:replace(option(source_ext, NeoOpts), "\.", "\\\\\\\\.", [{return, list}]), - AllRefs = - lists:append( - lists:map( - fun(F) -> - {ok, Res} = rebar_utils:sh( - lists:flatten(["grep -o [^\\\"]*", - ExtMatch," ",F]), - [{use_stdout, false}]), - string:tokens(Res, "\n") - end, Step)), + + AllRefs = lists:append([begin + {ok, Res} = + rebar_utils:sh( + lists:flatten(["grep -o [^\\\"]*", + ExtMatch, " ", F]), + [{use_stdout, false}]), + string:tokens(Res, "\n") + end || F <- Step]), DocRoot = option(doc_root, NeoOpts), WithPaths = [ filename:join([DocRoot, F]) || F <- AllRefs ], Existing = [F || F <- WithPaths, filelib:is_regular(F)], diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl index c1a6500..3bcbb26 100644 --- a/src/rebar_port_compiler.erl +++ b/src/rebar_port_compiler.erl @@ -119,7 +119,10 @@ clean(Config, AppFile) -> rebar_file_utils:delete_each([source_to_bin(S) || S <- Sources]), %% Delete the .so file - rebar_file_utils:delete_each(lists:map(fun({SoName,_}) -> SoName end, so_specs(Config, AppFile, expand_objects(Sources)))), + ExtractSoName = fun({SoName, _}) -> SoName end, + rebar_file_utils:delete_each([ExtractSoName(S) + || S <- so_specs(Config, AppFile, + expand_objects(Sources))]), %% Run the cleanup script, if it exists run_cleanup_hook(Config). diff --git a/src/rebar_reltool.erl b/src/rebar_reltool.erl index b8e1095..d375e97 100644 --- a/src/rebar_reltool.erl +++ b/src/rebar_reltool.erl @@ -222,13 +222,15 @@ run_reltool(Server, _Config, ReltoolConfig) -> end, %% Finally, overlay the files specified by the overlay section - case lists:keysearch(overlay, 1, ReltoolConfig) of - {value, {overlay, Overlay}} when is_list(Overlay) -> - execute_overlay(Overlay, OverlayVars, rebar_utils:get_cwd(), TargetDir); - {value, _} -> - ?ABORT("{overlay, [...]} entry in reltool.config must be a list.\n", []); + case lists:keyfind(overlay, 1, ReltoolConfig) of + {overlay, Overlay} when is_list(Overlay) -> + execute_overlay(Overlay, OverlayVars, rebar_utils:get_cwd(), + TargetDir); false -> - ?INFO("No {overlay, [...]} found in reltool.config.\n", []) + ?INFO("No {overlay, [...]} found in reltool.config.\n", []); + _ -> + ?ABORT("{overlay, [...]} entry in reltool.config " + "must be a list.\n", []) end; {error, Reason} -> diff --git a/src/rebar_require_vsn.erl b/src/rebar_require_vsn.erl index 96fc088..be51be9 100644 --- a/src/rebar_require_vsn.erl +++ b/src/rebar_require_vsn.erl @@ -45,7 +45,8 @@ eunit(Config, _) -> check_versions(Config) -> ErtsRegex = rebar_config:get(Config, require_erts_vsn, ".*"), - case re:run(erlang:system_info(version), ErtsRegex, [{capture, none}]) of + ReOpts = [{capture, none}], + case re:run(erlang:system_info(version), ErtsRegex, ReOpts) of match -> ?DEBUG("Matched required ERTS version: ~s -> ~s\n", [erlang:system_info(version), ErtsRegex]); @@ -55,7 +56,7 @@ check_versions(Config) -> end, OtpRegex = rebar_config:get(Config, require_otp_vsn, ".*"), - case re:run(erlang:system_info(otp_release), OtpRegex, [{capture, none}]) of + case re:run(erlang:system_info(otp_release), OtpRegex, ReOpts) of match -> ?DEBUG("Matched required OTP release: ~s -> ~s\n", [erlang:system_info(otp_release), OtpRegex]); diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index f49969a..a9ed9a0 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -75,8 +75,8 @@ sh(Command0, Options0) -> ?INFO("sh: ~s\n~p\n", [Command0, Options0]), DefaultOptions = [use_stdout, abort_on_error], - Options = lists:map(fun expand_sh_flag/1, - proplists:compact(Options0 ++ DefaultOptions)), + Options = [expand_sh_flag(V) + || V <- proplists:compact(Options0 ++ DefaultOptions)], ErrorHandler = proplists:get_value(error_handler, Options), OutputHandler = proplists:get_value(output_handler, Options), @@ -87,8 +87,8 @@ sh(Command0, Options0) -> Port = open_port({spawn, Command}, PortSettings), case sh_loop(Port, OutputHandler, []) of - {ok, Output} -> - {ok, Output}; + {ok, _Output} = Ok -> + Ok; {error, Rc} -> ErrorHandler(Command, Rc) end. @@ -179,10 +179,10 @@ expand_sh_flag({use_stdout, false}) -> fun(Line, Acc) -> [Acc | Line] end}; -expand_sh_flag({cd, Dir}) -> - {port_settings, {cd, Dir}}; -expand_sh_flag({env, Env}) -> - {port_settings, {env, Env}}. +expand_sh_flag({cd, _CdArg} = Cd) -> + {port_settings, Cd}; +expand_sh_flag({env, _EnvArg} = Env) -> + {port_settings, Env}. -spec log_and_abort(string(), integer()) -> no_return(). log_and_abort(Command, Rc) -> diff --git a/test/rebar_eunit_tests.erl b/test/rebar_eunit_tests.erl index 70e5d33..4179c9b 100644 --- a/test/rebar_eunit_tests.erl +++ b/test/rebar_eunit_tests.erl @@ -252,5 +252,5 @@ assert_full_coverage(Mod) -> string:str(X, Mod) =/= 0, string:str(X, "100%") =/= 0], file:close(F), - ?assert(length(Result) == 1) + ?assert(length(Result) =:= 1) end. -- cgit v1.1 From 150c9d0b470b5177282a1f005986cba75c689ebb Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sun, 9 Jan 2011 11:54:40 +0100 Subject: Simplify and cleanup rebar_xref --- src/rebar_xref.erl | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/src/rebar_xref.erl b/src/rebar_xref.erl index 0e29792..05bb46b 100644 --- a/src/rebar_xref.erl +++ b/src/rebar_xref.erl @@ -121,7 +121,7 @@ filter_away_ignored(UnusedExports) -> [{Mod, F, A} || {F, A} <- Ignore ++ lists:flatten(Callbacks)] end, AttrIgnore = lists:flatten(lists:map(F, lists:usort([M || {M, _, _} <- UnusedExports]))), - [X || X <- UnusedExports, not(lists:member(X, AttrIgnore))]. + [X || X <- UnusedExports, not lists:member(X, AttrIgnore)]. kf(Key, List) -> @@ -147,6 +147,7 @@ format_fa({_M, F, A}) -> %% %% Extract an element from a tuple, or undefined if N > tuple size +%% safe_element(N, Tuple) -> case catch(element(N, Tuple)) of {'EXIT', {badarg, _}} -> @@ -155,23 +156,6 @@ safe_element(N, Tuple) -> Value end. -%% -%% Extract the line number for a given function def -%% -abstract_code_function_line(Code, Name, Args) -> - [{function, Line, Name, _, _}] = [E || E <- Code, - safe_element(1, E) == function, - safe_element(3, E) == Name, - safe_element(4, E) == Args], - Line. - -%% -%% Extract the original source filename from the abstract code -%% -abstract_code_source_file(Code) -> - [{attribute, 1, file, {Name, _}} | _] = Code, - Name. - %% %% Given a MFA, find the file and LOC where it's defined. Note that @@ -182,7 +166,11 @@ find_mfa_source({M, F, A}) -> {M, Bin, _} = code:get_object_code(M), {ok, {M, [{abstract_code, AbstractCode}]}} = beam_lib:chunks(Bin, [abstract_code]), {raw_abstract_v1, Code} = AbstractCode, - Source = abstract_code_source_file(Code), - Line = abstract_code_function_line(Code, F, A), + %% Extract the original source filename from the abstract code + [{attribute, 1, file, {Source, _}} | _] = Code, + %% Extract the line number for a given function def + [{function, Line, F, _, _}] = [E || E <- Code, + safe_element(1, E) == function, + safe_element(3, E) == F, + safe_element(4, E) == A], {Source, Line}. - -- cgit v1.1 From 3b0568ebb7a43b2e3d30aab97265e60bc618f1a9 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sun, 9 Jan 2011 12:29:41 +0100 Subject: Simplify and cleanup rebar_templater --- src/rebar_templater.erl | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl index 748c8b6..5a02511 100644 --- a/src/rebar_templater.erl +++ b/src/rebar_templater.erl @@ -75,11 +75,13 @@ create(_Config, _) -> AvailTemplates = find_disk_templates() ++ find_escript_templates(), ?DEBUG("Available templates: ~p\n", [AvailTemplates]), + TemplateId = template_id(), + %% Using the specified template id, find the matching template file/type. %% Note that if you define the same template in both ~/.rebar/templates %% that is also present in the escript, the one on the file system will %% be preferred. - {Type, Template} = select_template(AvailTemplates, template_id()), + {Type, Template} = select_template(AvailTemplates, TemplateId), %% Load the template definition as is and get the list of variables the %% template requires. @@ -92,31 +94,31 @@ create(_Config, _) -> ?ABORT("Failed while processing variables from template ~p." "Variable definitions must follow form of " "[{atom(), term()}]. Failed at: ~p\n", - [template_id(), Entry]); + [TemplateId, Entry]); Context0 -> ok end; false -> ?WARN("No variables section found in template ~p; using empty context.\n", - [template_id()]), + [TemplateId]), Context0 = dict:new() end, %% For each variable, see if it's defined in global vars -- if it is, prefer that %% value over the defaults Context1 = update_vars(dict:fetch_keys(Context0), Context0), - ?DEBUG("Template ~p context: ~p\n", [template_id(), dict:to_list(Context1)]), + ?DEBUG("Template ~p context: ~p\n", [TemplateId, dict:to_list(Context1)]), %% Handle variables that possibly include other variables in their %% definition Context = resolve_recursive_vars(dict:to_list(Context1), Context1), - ?DEBUG("Resolved Template ~p context: ~p\n", [template_id(), dict:to_list(Context1)]), + ?DEBUG("Resolved Template ~p context: ~p\n", [TemplateId, dict:to_list(Context1)]), %% Now, use our context to process the template definition -- this permits us to %% use variables within the definition for filenames. FinalTemplate = consult(render(load_file(Type, Template), Context)), - ?DEBUG("Final template def ~p: ~p\n", [template_id(), FinalTemplate]), + ?DEBUG("Final template def ~p: ~p\n", [TemplateId, FinalTemplate]), %% Execute the instructions in the finalized template Force = rebar_config:get_global(force, "0"), @@ -215,7 +217,6 @@ update_vars([Key | Rest], Dict) -> %% Given a list of key value pairs, for each string value attempt to %% render it using Dict as the context. Storing the result in Dict as Key. %% - resolve_recursive_vars([], Dict) -> Dict; resolve_recursive_vars([{Key, Value0} | Rest], Dict) when is_list(Value0) -> @@ -266,11 +267,11 @@ write_file(Output, Data, Force) -> case Force =:= "1" orelse FileExists =:= false of true -> ok = filelib:ensure_dir(Output), - if - {Force, FileExists} =:= {"1", true} -> + case {Force, FileExists} of + {"1", true} -> ?CONSOLE("Writing ~s (forcibly overwriting)~n", [Output]); - true -> + _ -> ?CONSOLE("Writing ~s~n", [Output]) end, case file:write_file(Output, Data) of -- cgit v1.1 From bb6731208e1dce5255e820d5c5fe2763aa491991 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sun, 9 Jan 2011 12:34:19 +0100 Subject: Fix indentation in rebar_ct --- src/rebar_ct.erl | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/rebar_ct.erl b/src/rebar_ct.erl index 0c8e2ef..74399ee 100644 --- a/src/rebar_ct.erl +++ b/src/rebar_ct.erl @@ -77,13 +77,13 @@ run_test(TestDir, Config, _File) -> clear_log(RawLog) -> case filelib:ensure_dir("logs/index.html") of - ok -> - NowStr = rebar_utils:now_str(), - LogHeader = "--- Test run on " ++ NowStr ++ " ---\n", - ok = file:write_file(RawLog, LogHeader); - {error, Reason} -> - ?ERROR("Could not create log dir - ~p\n", [Reason]), - ?FAIL + ok -> + NowStr = rebar_utils:now_str(), + LogHeader = "--- Test run on " ++ NowStr ++ " ---\n", + ok = file:write_file(RawLog, LogHeader); + {error, Reason} -> + ?ERROR("Could not create log dir - ~p\n", [Reason]), + ?FAIL end. %% calling ct with erl does not return non-zero on failure - have to check @@ -96,28 +96,28 @@ check_log(RawLog) -> RunFailed = string:str(Msg, ", 0 failed") =:= 0, if MakeFailed -> - show_log(RawLog), - ?ERROR("Building tests failed\n",[]), - ?FAIL; + show_log(RawLog), + ?ERROR("Building tests failed\n",[]), + ?FAIL; RunFailed -> - show_log(RawLog), - ?ERROR("One or more tests failed\n",[]), - ?FAIL; + show_log(RawLog), + ?ERROR("One or more tests failed\n",[]), + ?FAIL; - true -> - ?CONSOLE("DONE. ~s\n", [Msg]) + true -> + ?CONSOLE("DONE. ~s\n", [Msg]) end. %% Show the log if it hasn't already been shown because verbose was on show_log(RawLog) -> ?CONSOLE("Showing log\n", []), case rebar_config:get_global(verbose, "0") of - "0" -> - {ok, Contents} = file:read_file(RawLog), - ?CONSOLE("~s", [Contents]); - _ -> - ok + "0" -> + {ok, Contents} = file:read_file(RawLog), + ?CONSOLE("~s", [Contents]); + _ -> + ok end. make_cmd(TestDir, Config) -> -- cgit v1.1 From ebcae06928c431a36187153b4c8f3d4366479051 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sun, 9 Jan 2011 14:22:50 +0100 Subject: Fix grep invocations --- src/rebar_erlydtl_compiler.erl | 15 ++++++++++----- src/rebar_neotoma_compiler.erl | 21 +++++++++++++-------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/rebar_erlydtl_compiler.erl b/src/rebar_erlydtl_compiler.erl index d30b56c..35a548d 100644 --- a/src/rebar_erlydtl_compiler.erl +++ b/src/rebar_erlydtl_compiler.erl @@ -162,14 +162,19 @@ referenced_dtls1(Step, Config, Seen) -> DtlOpts = erlydtl_opts(Config), ExtMatch = re:replace(option(source_ext, DtlOpts), "\.", "\\\\\\\\.", [{return, list}]), + + ShOpts = [{use_stdout, false}, return_on_error], AllRefs = lists:append( [begin - {ok, Res} = rebar_utils:sh( - lists:flatten(["grep -o [^\\\"]*", - ExtMatch," ",F]), - [{use_stdout, false}]), - string:tokens(Res, "\n") + Cmd = lists:flatten(["grep -o [^\\\"]*", + ExtMatch, " ", F]), + case rebar_utils:sh(Cmd, ShOpts) of + {ok, Res} -> + string:tokens(Res, "\n"); + {error, _} -> + "" + end end || F <- Step]), DocRoot = option(doc_root, DtlOpts), WithPaths = [ filename:join([DocRoot, F]) || F <- AllRefs ], diff --git a/src/rebar_neotoma_compiler.erl b/src/rebar_neotoma_compiler.erl index e67007c..e46caf4 100644 --- a/src/rebar_neotoma_compiler.erl +++ b/src/rebar_neotoma_compiler.erl @@ -122,14 +122,19 @@ referenced_pegs1(Step, Config, Seen) -> ExtMatch = re:replace(option(source_ext, NeoOpts), "\.", "\\\\\\\\.", [{return, list}]), - AllRefs = lists:append([begin - {ok, Res} = - rebar_utils:sh( - lists:flatten(["grep -o [^\\\"]*", - ExtMatch, " ", F]), - [{use_stdout, false}]), - string:tokens(Res, "\n") - end || F <- Step]), + ShOpts = [{use_stdout, false}, return_on_error], + AllRefs = + lists:append( + [begin + Cmd = lists:flatten(["grep -o [^\\\"]*", + ExtMatch, " ", F]), + case rebar_utils:sh(Cmd, ShOpts) of + {ok, Res} -> + string:tokens(Res, "\n"); + {error, _} -> + "" + end + end || F <- Step]), DocRoot = option(doc_root, NeoOpts), WithPaths = [ filename:join([DocRoot, F]) || F <- AllRefs ], Existing = [F || F <- WithPaths, filelib:is_regular(F)], -- cgit v1.1 From 27019e28672fafe62910b72f02c55ddf241cfb39 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Mon, 10 Jan 2011 15:50:04 +0100 Subject: Fix code clarity in bootstrap --- bootstrap | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/bootstrap b/bootstrap index 5be3183..c30c6dc 100755 --- a/bootstrap +++ b/bootstrap @@ -19,12 +19,10 @@ main(Args) -> end, %% Add check for debug flag - case lists:member("debug", Args) of - true -> - DebugFlag = debug_info; - false -> - DebugFlag = undefined - end, + DebugFlag = case lists:member("debug", Args) of + true -> debug_info; + false -> undefined + end, %% Compile all src/*.erl to ebin case make:files(filelib:wildcard("src/*.erl"), [{outdir, "ebin"}, {i, "include"}, -- cgit v1.1 From 932eb2e34335f0f6a4ee845cb5e2e8acec71c831 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Tue, 11 Jan 2011 11:54:10 +0100 Subject: Simplify rebar_core --- src/rebar_core.erl | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 353a218..edf220f 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -120,7 +120,7 @@ parse_args(Args) -> case getopt:parse(OptSpecList, Args) of {ok, {Options, NonOptArgs}} -> %% Check options and maybe halt execution - {ok, continue} = show_info_maybe_halt(Options, NonOptArgs), + ok = show_info_maybe_halt(Options, NonOptArgs), %% Set global variables based on getopt options set_global_flag(Options, verbose), @@ -165,31 +165,25 @@ set_global_flag(Options, Flag) -> %% show info and maybe halt execution %% show_info_maybe_halt(Opts, NonOptArgs) -> - case proplists:get_bool(help, Opts) of - true -> + false = show_info_maybe_halt(help, Opts, fun help/0), + false = show_info_maybe_halt(commands, Opts, fun commands/0), + false = show_info_maybe_halt(version, Opts, fun version/0), + case NonOptArgs of + [] -> + ?CONSOLE("No command to run specified!~n",[]), help(), + halt(1); + _ -> + ok + end. + +show_info_maybe_halt(O, Opts, F) -> + case proplists:get_bool(O, Opts) of + true -> + F(), halt(0); false -> - case proplists:get_bool(commands, Opts) of - true -> - commands(), - halt(0); - false -> - case proplists:get_bool(version, Opts) of - true -> - version(), - halt(0); - false -> - case NonOptArgs of - [] -> - ?CONSOLE("No command to run specified!~n",[]), - help(), - halt(1); - _ -> - {ok, continue} - end - end - end + false end. %% -- cgit v1.1 From 8940f078014526831ca3e804c2e7d8231ef1d070 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Wed, 12 Jan 2011 13:04:21 +0100 Subject: Fix underspec (thanks Kostis Sagonas) --- src/rebar_erlc_compiler.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index f533d48..0166c09 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -164,7 +164,7 @@ doterl_compile(Config, OutDir, MoreSources) -> %% Internal functions %% =================================================================== --spec include_path(Source::string(), Config::#config{}) -> [string()]. +-spec include_path(Source::string(), Config::#config{}) -> [string(), ...]. include_path(Source, Config) -> ErlOpts = rebar_config:get(Config, erl_opts, []), ["include", filename:dirname(Source)] ++ proplists:get_all_values(i, ErlOpts). -- cgit v1.1 From d6445b0a15e845a8887b74ec0771f558062a22e8 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Thu, 13 Jan 2011 18:38:50 +0100 Subject: Update README: document known discrepancies --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 16f4541..9119a8f 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,17 @@ $ ./bootstrap debug $ dialyzer ebin -Wunmatched_returns -Werror_handling -Wrace_conditions -Wunderspecs +The following discrepancies are known and safe to ignore: +
+rebar_templater.erl:249: The call rebar_templater:consult(
+                                Cont1::erl_scan:return_cont(),'eof',
+                                Acc::[any()])
+                         contains an opaque term as 1st argument when terms
+                         of different types are expected in these positions
+rebar_utils.erl:144: Call to missing or unexported function escript:foldl/3
+rebar_utils.erl:165: The created fun has no local return
+
+ It is **strongly recommended** to check the code with [Tidier](http://tidier.softlab.ntua.gr:20000/tidier/getstarted). Select all transformation options and enable **automatic** -- cgit v1.1 From 260d08a61b078ddf10b043a2173cc84089bf95cb Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 14 Jan 2011 18:31:41 +0100 Subject: Update README: fix formatting --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9119a8f..4f3fe43 100644 --- a/README.md +++ b/README.md @@ -66,8 +66,13 @@ You can also tell Emacs to ignore file variables: Writing Commit Messages ----------------------- -One line summary (< 50 characters) +Structure your commit message like this: + +
+One line summary (less than 50 characters)
+
 Longer description (wrap at 72 characters)
+
### Summary -- cgit v1.1 From 1d113b9c25f4207c645214a9a8a15c852de2f365 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sat, 15 Jan 2011 10:20:35 +0100 Subject: Update README: coding style --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4f3fe43..aec9c32 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,12 @@ Clone the git repository: Contributing to rebar ===================== -Indentation ------------ +Coding style +------------ + +Avoid introducing trailing whitespace. + +### Indentation To have consistent indentation we have vi modeline/emacs local variable headers in rebar's source files. This works automatically with vi. -- cgit v1.1 From e66b8c5f7d00bb6c3ffa98d3e25f5ef0ca0646b1 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Mon, 17 Jan 2011 12:03:30 +0100 Subject: Update README: coding style --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index aec9c32..b683df1 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,9 @@ Contributing to rebar Coding style ------------ -Avoid introducing trailing whitespace. +Do not introduce trailing whitespace. + +Do not introduce lines longer than 80 characters. ### Indentation -- cgit v1.1 From b52b82cc29f7fca1b08668b45b7b29ad945614b1 Mon Sep 17 00:00:00 2001 From: Andrew Tunnell-Jones Date: Mon, 10 Jan 2011 00:29:22 +0000 Subject: Add support for arch specific port_sources On one project I have a need to specify port_sources on R14 only and on another different project port_sources for Darwin and Linux. To this end add support to handle tuples of the form {ArchRegex, PortSource} in the port_sources list, eg: {port_sources, [{"R14", ["c_src/*.c"]}]}. --- src/rebar_port_compiler.erl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl index 3bcbb26..e684042 100644 --- a/src/rebar_port_compiler.erl +++ b/src/rebar_port_compiler.erl @@ -37,7 +37,11 @@ %% Supported configuration variables: %% -%% * port_sources - Erlang list of files and/or wildcard strings to be compiled +%% * port_sources - Erlang list of files and/or wildcard strings to be +%% compiled. Platform specific sources can be specified +%% by enclosing a string in a tuple of the form +%% {Regex, String} wherein Regex is a regular expression +%% that is checked against the system architecture. %% %% * so_specs - Erlang list of tuples of the form {"priv/so_name.so", ["c_src/object_file_name.o"]} useful for %% building multiple *.so files. @@ -136,6 +140,14 @@ clean(Config, AppFile) -> expand_sources([], Acc) -> Acc; +expand_sources([{ArchRegex, Spec} | Rest], Acc) -> + case rebar_utils:is_arch(ArchRegex) of + true -> + Acc2 = filelib:wildcard(Spec) ++ Acc, + expand_sources(Rest, Acc2); + false -> + expand_sources(Rest, Acc) + end; expand_sources([Spec | Rest], Acc) -> Acc2 = filelib:wildcard(Spec) ++ Acc, expand_sources(Rest, Acc2). -- cgit v1.1 From 3cb4234af273ffdc5ea3fdc0050a3fb406e204f5 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Mon, 17 Jan 2011 16:53:16 +0100 Subject: Add Andrew Tunnell-Jones to THANKS file --- THANKS | 1 + 1 file changed, 1 insertion(+) diff --git a/THANKS b/THANKS index 2cf87a9..6d32211 100644 --- a/THANKS +++ b/THANKS @@ -36,3 +36,4 @@ Benjamin Nortier Magnus Klaar Anthony Ramine Charles McKnight +Andrew Tunnell-Jones -- cgit v1.1 From 0c191a5a604c1c3278715bd71856961230983638 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Mon, 17 Jan 2011 17:06:55 +0100 Subject: Update THANKS file --- THANKS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/THANKS b/THANKS index 6d32211..85c40bf 100644 --- a/THANKS +++ b/THANKS @@ -17,7 +17,7 @@ Chris Bernard Jeremy Raymond Bob Ippolito Alex Songe -Vagabond +Andrew Thompson Russell Brown Chris Chew Klas Johansson -- cgit v1.1 From 6ce2beebd06d046e1d0e912017717753b62fb85a Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 21 Jan 2011 16:11:07 +0100 Subject: Synchronize nodetool escript with riak version --- priv/templates/simplenode.nodetool | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/priv/templates/simplenode.nodetool b/priv/templates/simplenode.nodetool index 971f983..f4bedff 100644 --- a/priv/templates/simplenode.nodetool +++ b/priv/templates/simplenode.nodetool @@ -30,7 +30,8 @@ main(Args) -> ["reboot"] -> io:format("~p\n", [rpc:call(TargetNode, init, reboot, [], 60000)]); ["rpc", Module, Function | RpcArgs] -> - case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function), [RpcArgs], 60000) of + case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function), + [RpcArgs], 60000) of ok -> ok; {badrpc, Reason} -> @@ -39,6 +40,15 @@ main(Args) -> _ -> halt(1) end; + ["rpcterms", Module, Function, ArgsAsString] -> + case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function), + consult(ArgsAsString), 60000) of + {badrpc, Reason} -> + io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]), + halt(1); + Other -> + io:format("~p\n", [Other]) + end; Other -> io:format("Other: ~p\n", [Other]), io:format("Usage: nodetool {ping|stop|restart|reboot}\n") @@ -78,3 +88,28 @@ append_node_suffix(Name, Suffix) -> [Node] -> list_to_atom(lists:concat([Node, Suffix, os:getpid()])) end. + + +%% +%% Given a string or binary, parse it into a list of terms, ala file:consult/0 +%% +consult(Str) when is_list(Str) -> + consult([], Str, []); +consult(Bin) when is_binary(Bin)-> + consult([], binary_to_list(Bin), []). + +consult(Cont, Str, Acc) -> + case erl_scan:tokens(Cont, Str, 0) of + {done, Result, Remaining} -> + case Result of + {ok, Tokens, _} -> + {ok, Term} = erl_parse:parse_term(Tokens), + consult([], Remaining, [Term | Acc]); + {eof, _Other} -> + lists:reverse(Acc); + {error, Info, _} -> + {error, Info} + end; + {more, Cont1} -> + consult(Cont1, eof, Acc) + end. -- cgit v1.1 From ac5948d91029fc9875494be72dce022b2f937ff7 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 21 Jan 2011 16:12:09 +0100 Subject: Add file local variables to nodetool escript --- priv/templates/simplenode.nodetool | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/priv/templates/simplenode.nodetool b/priv/templates/simplenode.nodetool index f4bedff..cb524ce 100644 --- a/priv/templates/simplenode.nodetool +++ b/priv/templates/simplenode.nodetool @@ -1,4 +1,5 @@ -%% -*- erlang -*- +%% -*- mode:erlang;tab-width:4;erlang-indent-level:4;indent-tabs-mode:nil -*- +%% ex: ft=erlang ts=4 sw=4 et %% ------------------------------------------------------------------- %% %% nodetool: Helper Script for interacting with live nodes -- cgit v1.1 From a3615a4b82159b1c0e31b6bee250269ebc66ae27 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sun, 23 Jan 2011 16:05:25 +0100 Subject: Update getopt --- src/getopt.erl | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/getopt.erl b/src/getopt.erl index 5f9fe61..35e19ec 100644 --- a/src/getopt.erl +++ b/src/getopt.erl @@ -13,6 +13,13 @@ -export([parse/2, usage/2, usage/3, usage/4]). +-export_type([arg_type/0, + arg_value/0, + arg_spec/0, + simple_option/0, + compound_option/0, + option/0, + option_spec/0]). -define(TAB_LENGTH, 8). %% Indentation of the help messages in number of tabs. @@ -114,7 +121,7 @@ parse_option_long(OptSpecList, OptAcc, ArgAcc, ArgPos, Args, OptStr, OptArg) -> case lists:keyfind(Long, ?OPT_LONG, OptSpecList) of {Name, _Short, Long, undefined, _Help} -> parse(OptSpecList, [Name | OptAcc], ArgAcc, ArgPos, Args); - + {_Name, _Short, Long, _ArgSpec, _Help} = OptSpec -> % The option argument string is empty, but the option requires % an argument, so we look into the next string in the list. @@ -217,7 +224,7 @@ parse_option_next_arg(OptSpecList, OptAcc, ArgAcc, ArgPos, [] = Args, {Name, _Sh _ -> throw({error, {missing_option_arg, Name}}) end. - + %% @doc Find the option for the discrete argument in position specified in the %% Pos argument. @@ -318,7 +325,7 @@ is_arg_true(Arg) -> (Arg =:= "on") orelse (Arg =:= "enabled") orelse (Arg =:= "1"). - + -spec is_arg_false(string()) -> boolean(). is_arg_false(Arg) -> (Arg =:= "false") orelse (Arg =:= "f") orelse @@ -362,7 +369,7 @@ is_float_arg([_Head | _Tail]) -> false; is_float_arg([]) -> true. - + %% @doc Show a message on stdout indicating the command line options and %% arguments that are supported by the program. @@ -441,8 +448,8 @@ usage_options(OptSpecList) -> lists:flatten(lists:reverse(usage_options_reverse(OptSpecList, []))). usage_options_reverse([{Name, Short, Long, _ArgSpec, Help} | Tail], Acc) -> - Prefix = - case Long of + Prefix = + case Long of undefined -> case Short of % Neither short nor long form (non-option argument). -- cgit v1.1 From d1ff83a8989cd11fbbed794a97c6e13cf6388e21 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Mon, 24 Jan 2011 16:40:50 +0100 Subject: Move command line handling funs into rebar.erl --- src/rebar.erl | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/rebar_core.erl | 175 +------------------------------------------------- 2 files changed, 187 insertions(+), 173 deletions(-) diff --git a/src/rebar.erl b/src/rebar.erl index 74812f5..673a4c1 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -26,7 +26,16 @@ %% ------------------------------------------------------------------- -module(rebar). --export([main/1]). +-export([main/1, + help/0, + parse_args/1, + version/0]). + +-include("rebar.hrl"). + +%% ==================================================================== +%% Public API +%% ==================================================================== main(Args) -> case catch(rebar_core:run(Args)) of @@ -39,3 +48,177 @@ main(Args) -> io:format("Uncaught error in rebar_core: ~p\n", [Error]), halt(1) end. + +%% +%% print help/usage string +%% +help() -> + OptSpecList = option_spec_list(), + getopt:usage(OptSpecList, "rebar", + "[var=value,...] ", + [{"var=value", "rebar global variables (e.g. force=1)"}, + {"command", "Command to run (e.g. compile)"}]). + +%% +%% Parse command line arguments using getopt and also filtering out any +%% key=value pairs. What's left is the list of commands to run +%% +parse_args(Args) -> + %% Parse getopt options + OptSpecList = option_spec_list(), + case getopt:parse(OptSpecList, Args) of + {ok, {Options, NonOptArgs}} -> + %% Check options and maybe halt execution + ok = show_info_maybe_halt(Options, NonOptArgs), + + %% Set global variables based on getopt options + set_global_flag(Options, verbose), + set_global_flag(Options, force), + DefJobs = rebar_config:get_jobs(), + case proplists:get_value(jobs, Options, DefJobs) of + DefJobs -> + ok; + Jobs -> + rebar_config:set_global(jobs, Jobs) + end, + + %% Set the rebar config to use + case proplists:get_value(config, Options) of + undefined -> ok; + Conf -> rebar_config:set_global(config, Conf) + end, + + %% Filter all the flags (i.e. strings of form key=value) from the + %% command line arguments. What's left will be the commands to run. + filter_flags(NonOptArgs, []); + + {error, {Reason, Data}} -> + ?ERROR("Error: ~s ~p~n~n", [Reason, Data]), + rebar:help(), + halt(1) + end. + +%% +%% show version information and halt +%% +version() -> + {ok, Vsn} = application:get_key(rebar, vsn), + ?CONSOLE("rebar version: ~s date: ~s vcs: ~s\n", [Vsn, ?BUILD_TIME, ?VCS_INFO]). + + +%% ==================================================================== +%% Internal functions +%% ==================================================================== + +%% +%% set global flag based on getopt option boolean value +%% +set_global_flag(Options, Flag) -> + Value = case proplists:get_bool(Flag, Options) of + true -> + "1"; + false -> + "0" + end, + rebar_config:set_global(Flag, Value). + +%% +%% show info and maybe halt execution +%% +show_info_maybe_halt(Opts, NonOptArgs) -> + false = show_info_maybe_halt(help, Opts, fun help/0), + false = show_info_maybe_halt(commands, Opts, fun commands/0), + false = show_info_maybe_halt(version, Opts, fun version/0), + case NonOptArgs of + [] -> + ?CONSOLE("No command to run specified!~n",[]), + help(), + halt(1); + _ -> + ok + end. + +show_info_maybe_halt(O, Opts, F) -> + case proplists:get_bool(O, Opts) of + true -> + F(), + halt(0); + false -> + false + end. + +%% +%% print known commands +%% +commands() -> + S = <<" +dialyze Analyze with Dialyzer +build-plt Build Dialyzer PLT +check-plt Check Dialyzer PLT + +clean Clean +compile Compile sources + +create template= [var=foo,...] Create skel based on template and vars +create-app [appid=myapp] Create simple app skel +create-node [nodeid=mynode] Create simple node skel +list-templates List available templates + +doc Generate Erlang program documentation + +check-deps Display to be fetched dependencies +get-deps Fetch dependencies +update-deps Update fetched dependencies +delete-deps Delete fetched dependencies + +generate [dump_spec=0/1] Build release with reltool + +eunit [suite=foo] Run eunit [test/foo_tests.erl] tests +ct [suite=] [case=] Run common_test suites in ./test + +xref Run cross reference analysis + +help Show the program options +version Show version information +">>, + io:put_chars(S), + %% workaround to delay exit until all output is written + timer:sleep(300). + +%% +%% options accepted via getopt +%% +option_spec_list() -> + Jobs = rebar_config:get_jobs(), + JobsHelp = io_lib:format( + "Number of concurrent workers a command may use. Default: ~B", + [Jobs]), + [ + %% {Name, ShortOpt, LongOpt, ArgSpec, HelpMsg} + {help, $h, "help", undefined, "Show the program options"}, + {commands, $c, "commands", undefined, "Show available commands"}, + {verbose, $v, "verbose", undefined, "Be verbose about what gets done"}, + {version, $V, "version", undefined, "Show version information"}, + {force, $f, "force", undefined, "Force"}, + {jobs, $j, "jobs", integer, JobsHelp}, + {config, $C, "config", string, "Rebar config file to use"} + ]. + +%% +%% Seperate all commands (single-words) from flags (key=value) and store +%% values into the rebar_config global storage. +%% +filter_flags([], Commands) -> + lists:reverse(Commands); +filter_flags([Item | Rest], Commands) -> + case string:tokens(Item, "=") of + [Command] -> + filter_flags(Rest, [Command | Commands]); + [KeyStr, Value] -> + Key = list_to_atom(KeyStr), + rebar_config:set_global(Key, Value), + filter_flags(Rest, Commands); + Other -> + ?CONSOLE("Ignoring command line argument: ~p\n", [Other]), + filter_flags(Rest, Commands) + end. diff --git a/src/rebar_core.erl b/src/rebar_core.erl index edf220f..86607e2 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -47,12 +47,12 @@ %% =================================================================== run(["help"]) -> - help(), + rebar:help(), ok; run(["version"]) -> %% Load application spec and display vsn and build time info ok = application:load(rebar), - version(), + rebar:version(), ok; run(RawArgs) -> %% Pre-load the rebar app so that we get default configuration @@ -60,7 +60,7 @@ run(RawArgs) -> %% Parse out command line arguments -- what's left is a list of commands to %% run - Commands = parse_args(RawArgs), + Commands = rebar:parse_args(RawArgs), %% Make sure crypto is running ok = crypto:start(), @@ -110,175 +110,6 @@ skip_dirs() -> %% Internal functions %% =================================================================== -%% -%% Parse command line arguments using getopt and also filtering out any -%% key=value pairs. What's left is the list of commands to run -%% -parse_args(Args) -> - %% Parse getopt options - OptSpecList = option_spec_list(), - case getopt:parse(OptSpecList, Args) of - {ok, {Options, NonOptArgs}} -> - %% Check options and maybe halt execution - ok = show_info_maybe_halt(Options, NonOptArgs), - - %% Set global variables based on getopt options - set_global_flag(Options, verbose), - set_global_flag(Options, force), - DefJobs = rebar_config:get_jobs(), - case proplists:get_value(jobs, Options, DefJobs) of - DefJobs -> - ok; - Jobs -> - rebar_config:set_global(jobs, Jobs) - end, - - %% Set the rebar config to use - case proplists:get_value(config, Options) of - undefined -> ok; - Conf -> rebar_config:set_global(config, Conf) - end, - - %% Filter all the flags (i.e. strings of form key=value) from the - %% command line arguments. What's left will be the commands to run. - filter_flags(NonOptArgs, []); - - {error, {Reason, Data}} -> - ?ERROR("Error: ~s ~p~n~n", [Reason, Data]), - help(), - halt(1) - end. - -%% -%% set global flag based on getopt option boolean value -%% -set_global_flag(Options, Flag) -> - Value = case proplists:get_bool(Flag, Options) of - true -> - "1"; - false -> - "0" - end, - rebar_config:set_global(Flag, Value). - -%% -%% show info and maybe halt execution -%% -show_info_maybe_halt(Opts, NonOptArgs) -> - false = show_info_maybe_halt(help, Opts, fun help/0), - false = show_info_maybe_halt(commands, Opts, fun commands/0), - false = show_info_maybe_halt(version, Opts, fun version/0), - case NonOptArgs of - [] -> - ?CONSOLE("No command to run specified!~n",[]), - help(), - halt(1); - _ -> - ok - end. - -show_info_maybe_halt(O, Opts, F) -> - case proplists:get_bool(O, Opts) of - true -> - F(), - halt(0); - false -> - false - end. - -%% -%% print help/usage string -%% -help() -> - OptSpecList = option_spec_list(), - getopt:usage(OptSpecList, "rebar", - "[var=value,...] ", - [{"var=value", "rebar global variables (e.g. force=1)"}, - {"command", "Command to run (e.g. compile)"}]). - -%% -%% print known commands -%% -commands() -> - S = <<" -dialyze Analyze with Dialyzer -build-plt Build Dialyzer PLT -check-plt Check Dialyzer PLT - -clean Clean -compile Compile sources - -create template= [var=foo,...] Create skel based on template and vars -create-app [appid=myapp] Create simple app skel -create-node [nodeid=mynode] Create simple node skel -list-templates List available templates - -doc Generate Erlang program documentation - -check-deps Display to be fetched dependencies -get-deps Fetch dependencies -update-deps Update fetched dependencies -delete-deps Delete fetched dependencies - -generate [dump_spec=0/1] Build release with reltool - -eunit [suite=foo] Run eunit [test/foo_tests.erl] tests -ct [suite=] [case=] Run common_test suites in ./test - -xref Run cross reference analysis - -help Show the program options -version Show version information -">>, - io:put_chars(S), - %% workaround to delay exit until all output is written - timer:sleep(300). - -%% -%% show version information and halt -%% -version() -> - {ok, Vsn} = application:get_key(rebar, vsn), - ?CONSOLE("rebar version: ~s date: ~s vcs: ~s\n", [Vsn, ?BUILD_TIME, ?VCS_INFO]). - -%% -%% options accepted via getopt -%% -option_spec_list() -> - Jobs = rebar_config:get_jobs(), - JobsHelp = io_lib:format( - "Number of concurrent workers a command may use. Default: ~B", - [Jobs]), - [ - %% {Name, ShortOpt, LongOpt, ArgSpec, HelpMsg} - {help, $h, "help", undefined, "Show the program options"}, - {commands, $c, "commands", undefined, "Show available commands"}, - {verbose, $v, "verbose", undefined, "Be verbose about what gets done"}, - {version, $V, "version", undefined, "Show version information"}, - {force, $f, "force", undefined, "Force"}, - {jobs, $j, "jobs", integer, JobsHelp}, - {config, $C, "config", string, "Rebar config file to use"} - ]. - -%% -%% Seperate all commands (single-words) from flags (key=value) and store -%% values into the rebar_config global storage. -%% -filter_flags([], Commands) -> - lists:reverse(Commands); -filter_flags([Item | Rest], Commands) -> - case string:tokens(Item, "=") of - [Command] -> - filter_flags(Rest, [Command | Commands]); - [KeyStr, Value] -> - Key = list_to_atom(KeyStr), - rebar_config:set_global(Key, Value), - filter_flags(Rest, Commands); - Other -> - ?CONSOLE("Ignoring command line argument: ~p\n", [Other]), - filter_flags(Rest, Commands) - end. - process_commands([]) -> case erlang:get(operations) of 0 -> -- cgit v1.1 From 6978504d43de4d12d791db974e4748e2cb4c2092 Mon Sep 17 00:00:00 2001 From: Klas Johansson Date: Mon, 24 Jan 2011 16:55:18 +0100 Subject: Add support for abbreviated command names This change makes it possible to type the beginning (the prefix) of a command name and rebar will guess the full name of the command, thereby saving the user precious keystrokes. As long as the prefix matches only one command, rebar runs that command, otherwise rebar prints a list of candidate command names. The "-" character is considered to be a word separator and the prefix matching is done per word. Example prefix matches: co ==> compile cl ==> clean create ==> create create-a ==> create-app c-a ==> create-app c-app ==> create-app --- src/rebar.erl | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/rebar_core.erl | 21 +++++++++-------- 2 files changed, 75 insertions(+), 12 deletions(-) diff --git a/src/rebar.erl b/src/rebar.erl index 673a4c1..69725b3 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -90,7 +90,7 @@ parse_args(Args) -> %% Filter all the flags (i.e. strings of form key=value) from the %% command line arguments. What's left will be the commands to run. - filter_flags(NonOptArgs, []); + unabbreviate_command_names(filter_flags(NonOptArgs, [])); {error, {Reason, Data}} -> ?ERROR("Error: ~s ~p~n~n", [Reason, Data]), @@ -222,3 +222,67 @@ filter_flags([Item | Rest], Commands) -> ?CONSOLE("Ignoring command line argument: ~p\n", [Other]), filter_flags(Rest, Commands) end. + +command_names() -> + ["build-plt", "check-deps", "check-plt", "clean", "compile", "create", + "create-app", "create-node", "ct", "delete-deps", "dialyze", "doc", + "eunit", "generate", "get-deps", "help", "list-templates", "update-deps", + "version", "xref"]. + +unabbreviate_command_names([]) -> + []; +unabbreviate_command_names([Command | Commands]) -> + case get_command_name_candidates(Command) of + [] -> + %% let the rest of the code detect that the command doesn't exist + %% (this would perhaps be a good place to fail) + [Command | unabbreviate_command_names(Commands)]; + [FullCommand] -> + [FullCommand | unabbreviate_command_names(Commands)]; + Candidates -> + ?ABORT("Found more than one match for abbreviated command name " + " '~s',~nplease be more specific. Possible candidates:~n" + " ~s~n", + [Command, string:join(Candidates, ", ")]) + end. + +get_command_name_candidates(Command) -> + %% Get the command names which match the given (abbreviated) command name. + %% * "c" matches commands like compile, clean and create-app + %% * "create" matches command create only, since it's unique + %% * "create-" matches commands starting with create- + %% * "c-a" matches create-app + %% * "create-a" matches create-app + %% * "c-app" matches create-app + Candidates = [Candidate || Candidate <- command_names(), + is_command_name_candidate(Command, Candidate)], + %% Is there a complete match? If so return only that, return a + %% list of candidates otherwise + case Candidates of + [Command] = Match -> Match; + _ -> Candidates + end. + +is_command_name_candidate(Command, Candidate) -> + lists:prefix(Command, Candidate) + orelse is_command_name_sub_word_candidate(Command, Candidate). + +is_command_name_sub_word_candidate(Command, Candidate) -> + %% Allow for parts of commands to be abbreviated, i.e. create-app + %% can be shortened to "create-a", "c-a" or "c-app" (but not + %% "create-" since that would be ambiguous). + CommandSubWords = re:split(Command, "-", [{return, list}]), + CandidateSubWords = re:split(Candidate, "-", [{return, list}]), + is_command_name_sub_word_candidate_aux(CommandSubWords, CandidateSubWords). + +is_command_name_sub_word_candidate_aux([CmdSW | CmdSWs], [CandSW | CandSWs]) -> + case lists:prefix(CmdSW, CandSW) of + true -> + is_command_name_sub_word_candidate_aux(CmdSWs, CandSWs); + false -> + false + end; +is_command_name_sub_word_candidate_aux([], []) -> + true; +is_command_name_sub_word_candidate_aux(_CmdSWs, _CandSWs) -> + false. diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 86607e2..cb08cdf 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -46,22 +46,21 @@ %% Public API %% =================================================================== -run(["help"]) -> - rebar:help(), - ok; -run(["version"]) -> - %% Load application spec and display vsn and build time info - ok = application:load(rebar), - rebar:version(), - ok; run(RawArgs) -> %% Pre-load the rebar app so that we get default configuration ok = application:load(rebar), - %% Parse out command line arguments -- what's left is a list of commands to - %% run - Commands = rebar:parse_args(RawArgs), + %% run -- and start running commands + run_aux(rebar:parse_args(RawArgs)). +run_aux(["help"]) -> + rebar:help(), + ok; +run_aux(["version"]) -> + %% Display vsn and build time info + rebar:version(), + ok; +run_aux(Commands) -> %% Make sure crypto is running ok = crypto:start(), -- cgit v1.1 From a8066b35a9d0bdbc360e57db829d8fab65a70d15 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 25 Jan 2011 21:29:08 -0700 Subject: Use an order independent method for exact matches when looking for command candidates --- src/rebar.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rebar.erl b/src/rebar.erl index 69725b3..5121f59 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -258,9 +258,9 @@ get_command_name_candidates(Command) -> is_command_name_candidate(Command, Candidate)], %% Is there a complete match? If so return only that, return a %% list of candidates otherwise - case Candidates of - [Command] = Match -> Match; - _ -> Candidates + case lists:member(Command, Candidates) of + true -> [Command]; + false -> Candidates end. is_command_name_candidate(Command, Candidate) -> -- cgit v1.1 From 3fd3bfc89a614728c21360ecb91d8a5029f7d0b3 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Thu, 27 Jan 2011 15:52:48 +0100 Subject: Fix circular dependency --- src/rebar.erl | 50 ++++++++++++++++++++++++++++++++++++++++++++------ src/rebar_core.erl | 40 +--------------------------------------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/rebar.erl b/src/rebar.erl index 5121f59..1b502b1 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -38,7 +38,7 @@ %% ==================================================================== main(Args) -> - case catch(rebar_core:run(Args)) of + case catch(run(Args)) of ok -> ok; {error, failed} -> @@ -49,6 +49,48 @@ main(Args) -> halt(1) end. +%% ==================================================================== +%% Internal functions +%% ==================================================================== + +run(RawArgs) -> + %% Pre-load the rebar app so that we get default configuration + ok = application:load(rebar), + %% Parse out command line arguments -- what's left is a list of commands to + %% run -- and start running commands + run_aux(parse_args(RawArgs)). + +run_aux(["help"]) -> + help(), + ok; +run_aux(["version"]) -> + %% Display vsn and build time info + version(), + ok; +run_aux(Commands) -> + %% Make sure crypto is running + ok = crypto:start(), + + %% Initialize logging system + rebar_log:init(), + + %% Convert command strings to atoms + CommandAtoms = [list_to_atom(C) || C <- Commands], + + %% Determine the location of the rebar executable; important for pulling + %% resources out of the escript + rebar_config:set_global(escript, filename:absname(escript:script_name())), + ?DEBUG("Rebar location: ~p\n", [rebar_config:get_global(escript, undefined)]), + + %% Note the top-level directory for reference + rebar_config:set_global(base_dir, filename:absname(rebar_utils:get_cwd())), + + %% Keep track of how many operations we do, so we can detect bad commands + erlang:put(operations, 0), + + %% Process each command, resetting any state between each one + rebar_core:process_commands(CommandAtoms). + %% %% print help/usage string %% @@ -94,7 +136,7 @@ parse_args(Args) -> {error, {Reason, Data}} -> ?ERROR("Error: ~s ~p~n~n", [Reason, Data]), - rebar:help(), + help(), halt(1) end. @@ -106,10 +148,6 @@ version() -> ?CONSOLE("rebar version: ~s date: ~s vcs: ~s\n", [Vsn, ?BUILD_TIME, ?VCS_INFO]). -%% ==================================================================== -%% Internal functions -%% ==================================================================== - %% %% set global flag based on getopt option boolean value %% diff --git a/src/rebar_core.erl b/src/rebar_core.erl index cb08cdf..1c3940f 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -26,7 +26,7 @@ %% ------------------------------------------------------------------- -module(rebar_core). --export([run/1, +-export([process_commands/1, skip_dir/1, is_skip_dir/1, skip_dirs/0]). @@ -46,44 +46,6 @@ %% Public API %% =================================================================== -run(RawArgs) -> - %% Pre-load the rebar app so that we get default configuration - ok = application:load(rebar), - %% Parse out command line arguments -- what's left is a list of commands to - %% run -- and start running commands - run_aux(rebar:parse_args(RawArgs)). - -run_aux(["help"]) -> - rebar:help(), - ok; -run_aux(["version"]) -> - %% Display vsn and build time info - rebar:version(), - ok; -run_aux(Commands) -> - %% Make sure crypto is running - ok = crypto:start(), - - %% Initialize logging system - rebar_log:init(), - - %% Convert command strings to atoms - CommandAtoms = [list_to_atom(C) || C <- Commands], - - %% Determine the location of the rebar executable; important for pulling - %% resources out of the escript - rebar_config:set_global(escript, filename:absname(escript:script_name())), - ?DEBUG("Rebar location: ~p\n", [rebar_config:get_global(escript, undefined)]), - - %% Note the top-level directory for reference - rebar_config:set_global(base_dir, filename:absname(rebar_utils:get_cwd())), - - %% Keep track of how many operations we do, so we can detect bad commands - erlang:put(operations, 0), - - %% Process each command, resetting any state between each one - process_commands(CommandAtoms). - skip_dir(Dir) -> SkipDir = {skip_dir, Dir}, case erlang:get(SkipDir) of -- cgit v1.1 From 5298e93a180e6db87a33f26eb6a2db06e8065dc7 Mon Sep 17 00:00:00 2001 From: joewilliams Date: Thu, 27 Jan 2011 18:15:25 +0100 Subject: Add 'generate-upgrade' command To support OTP release upgrades I have added support for building upgrade packages. Support for this is included in the rebar_upgrade module, specifically generate_upgrade/2. It requires one variable to be set on the command line 'previous_release' which is the absolute path or relative path from 'rel/' to the previous release one is upgrading from. Running an upgrade will create the needed files, including a relup and result in a tarball containing the upgrade being written to 'rel/'. When done it cleans up the temporary files systools created. Usage: $ rebar generate-upgrade previous_release=/path/to/old/version This also includes a dummy application that can be used to test upgrades as well as an example. Special thanks to Daniel Reverri, Jesper Louis Andersen and Richard Jones for comments and patches. --- ebin/rebar.app | 4 +- priv/templates/simplenode.runner | 10 +- src/rebar.erl | 6 +- src/rebar_upgrade.erl | 206 +++++++++++++++++++++ test/upgrade_project/README.md | 38 ++++ test/upgrade_project/apps/dummy/ebin/dummy.appup | 8 + test/upgrade_project/apps/dummy/src/dummy.app.src | 9 + test/upgrade_project/apps/dummy/src/dummy_app.erl | 9 + .../apps/dummy/src/dummy_server.erl | 56 ++++++ test/upgrade_project/apps/dummy/src/dummy_sup.erl | 15 ++ test/upgrade_project/rebar.config | 4 + test/upgrade_project/rel/files/app.config | 10 + test/upgrade_project/rel/files/dummy | 155 ++++++++++++++++ test/upgrade_project/rel/files/erl | 34 ++++ test/upgrade_project/rel/files/nodetool | 116 ++++++++++++ test/upgrade_project/rel/files/vm.args | 20 ++ test/upgrade_project/rel/reltool.config | 25 +++ 17 files changed, 720 insertions(+), 5 deletions(-) create mode 100644 src/rebar_upgrade.erl create mode 100644 test/upgrade_project/README.md create mode 100644 test/upgrade_project/apps/dummy/ebin/dummy.appup create mode 100644 test/upgrade_project/apps/dummy/src/dummy.app.src create mode 100644 test/upgrade_project/apps/dummy/src/dummy_app.erl create mode 100644 test/upgrade_project/apps/dummy/src/dummy_server.erl create mode 100644 test/upgrade_project/apps/dummy/src/dummy_sup.erl create mode 100644 test/upgrade_project/rebar.config create mode 100644 test/upgrade_project/rel/files/app.config create mode 100755 test/upgrade_project/rel/files/dummy create mode 100755 test/upgrade_project/rel/files/erl create mode 100755 test/upgrade_project/rel/files/nodetool create mode 100644 test/upgrade_project/rel/files/vm.args create mode 100644 test/upgrade_project/rel/reltool.config diff --git a/ebin/rebar.app b/ebin/rebar.app index ad37c66..1f7db21 100644 --- a/ebin/rebar.app +++ b/ebin/rebar.app @@ -32,6 +32,7 @@ rebar_require_vsn, rebar_subdirs, rebar_templater, + rebar_upgrade, rebar_utils, rebar_xref, getopt, @@ -79,7 +80,8 @@ ]}, {rel_dir, [ - rebar_reltool + rebar_reltool, + rebar_upgrade ]} ]} ]} diff --git a/priv/templates/simplenode.runner b/priv/templates/simplenode.runner index 10c233b..ec6d7ff 100755 --- a/priv/templates/simplenode.runner +++ b/priv/templates/simplenode.runner @@ -117,13 +117,19 @@ case "$1" in $ERTS_PATH/to_erl $PIPE_DIR ;; - console) + console|console_clean) + # .boot file typically just $SCRIPT (ie, the app name) + # however, for debugging, sometimes start_clean.boot is useful: + case "$1" in + console) BOOTFILE=$SCRIPT ;; + console_clean) BOOTFILE=start_clean ;; + esac # Setup beam-required vars ROOTDIR=$RUNNER_BASE_DIR BINDIR=$ROOTDIR/erts-$ERTS_VSN/bin EMU=beam PROGNAME=`echo $0 | sed 's/.*\\///'` - CMD="$BINDIR/erlexec -boot $RUNNER_BASE_DIR/releases/$APP_VSN/$SCRIPT -embedded -config $RUNNER_ETC_DIR/app.config -args_file $RUNNER_ETC_DIR/vm.args -- ${1+"$@"}" + CMD="$BINDIR/erlexec -boot $RUNNER_BASE_DIR/releases/$APP_VSN/$BOOTFILE -embedded -config $RUNNER_ETC_DIR/app.config -args_file $RUNNER_ETC_DIR/vm.args -- ${1+"$@"}" export EMU export ROOTDIR export BINDIR diff --git a/src/rebar.erl b/src/rebar.erl index 1b502b1..6c99ab5 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -211,6 +211,8 @@ delete-deps Delete fetched dependencies generate [dump_spec=0/1] Build release with reltool +generate-upgrade [previous_release=path] Build an upgrade package + eunit [suite=foo] Run eunit [test/foo_tests.erl] tests ct [suite=] [case=] Run common_test suites in ./test @@ -264,8 +266,8 @@ filter_flags([Item | Rest], Commands) -> command_names() -> ["build-plt", "check-deps", "check-plt", "clean", "compile", "create", "create-app", "create-node", "ct", "delete-deps", "dialyze", "doc", - "eunit", "generate", "get-deps", "help", "list-templates", "update-deps", - "version", "xref"]. + "eunit", "generate", "generate-upgrade", "get-deps", "help", + "list-templates", "update-deps", "version", "xref"]. unabbreviate_command_names([]) -> []; diff --git a/src/rebar_upgrade.erl b/src/rebar_upgrade.erl new file mode 100644 index 0000000..4c0d2f7 --- /dev/null +++ b/src/rebar_upgrade.erl @@ -0,0 +1,206 @@ +%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% ex: ts=4 sw=4 et +%% ------------------------------------------------------------------- +%% +%% rebar: Erlang Build Tools +%% +%% Copyright (c) 2011 Joe Williams +%% +%% 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_upgrade). + +-include("rebar.hrl"). +-include_lib("kernel/include/file.hrl"). + +-export(['generate-upgrade'/2]). + +%% public api + +'generate-upgrade'(_Config, ReltoolFile) -> + case rebar_config:get_global(previous_release, false) of + false -> + ?ABORT("previous_release=PATH is required to " + "create upgrade package~n", []); + OldVerPath -> + %% Run checks to make sure that building a package is possible + {NewName, NewVer} = run_checks(OldVerPath, ReltoolFile), + 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), + + %% Build the package + run_systools(NameVer, NewName), + + %% Boot file changes + boot_files(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), + + %% Restore original path + true = code:set_path(OrigPath), + + ok + end. + +%% internal api + +run_checks(OldVerPath, ReltoolFile) -> + true = prop_check(filelib:is_dir(OldVerPath), + "Release directory doesn't exist (~p)~n", [OldVerPath]), + + {Name, Ver} = get_release_name(ReltoolFile), + + NamePath = filename:join([".", Name]), + true = prop_check(filelib:is_dir(NamePath), + "Release directory doesn't exist (~p)~n", [NamePath]), + + {NewName, NewVer} = get_release_version(Name, NamePath), + {OldName, OldVer} = get_release_version(Name, OldVerPath), + + true = prop_check(NewName == OldName, + "New and old .rel release names do not match~n", []), + true = prop_check(Name == NewName, + "Reltool and .rel release names do not match~n", []), + true = prop_check(NewVer =/= OldVer, + "New and old .rel contain the same version~n", []), + true = prop_check(Ver == NewVer, + "Reltool and .rel versions do not match~n", []), + + {NewName, NewVer}. + +get_release_name(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_release_version(Name, Path) -> + [RelFile] = filelib:wildcard(filename:join([Path, "releases", "*", + Name ++ ".rel"])), + [BinDir|_] = re:replace(RelFile, Name ++ "\\.rel", ""), + {ok, [{release, {Name1, Ver}, _, _}]} = + file:consult(filename:join([binary_to_list(BinDir), + Name ++ ".rel"])), + {Name1, Ver}. + +prop_check(true, _, _) -> true; +prop_check(false, Msg, Args) -> ?ABORT(Msg, Args). + +setup(OldVerPath, NewName, NewVer, NameVer) -> + NewRelPath = filename:join([".", NewName]), + Src = filename:join([NewRelPath, "releases", + NewVer, NewName ++ ".rel"]), + Dst = filename:join([".", NameVer ++ ".rel"]), + {ok, _} = file:copy(Src, Dst), + ok = code:add_pathsa( + lists:append([ + filelib:wildcard(filename:join([OldVerPath, + "releases", "*"])), + filelib:wildcard(filename:join([OldVerPath, + "lib", "*", "ebin"])), + filelib:wildcard(filename:join([NewRelPath, + "lib", "*", "ebin"])), + filelib:wildcard(filename:join([NewRelPath, "*"])) + ])). + +run_systools(NewVer, Name) -> + Opts = [silent], + NameList = [Name], + case systools:make_relup(NewVer, NameList, NameList, Opts) of + {error, _, _Message} -> + ?ABORT("Systools aborted with: ~p~n", [_Message]); + _ -> + ?DEBUG("Relup created~n", []), + case systools:make_script(NewVer, Opts) of + {error, _, _Message1} -> + ?ABORT("Systools aborted with: ~p~n", [_Message1]); + _ -> + ?DEBUG("Script created~n", []), + case systools:make_tar(NewVer, Opts) of + {error, _, _Message2} -> + ?ABORT("Systools aborted with: ~p~n", [_Message2]); + _ -> + ok + end + end + end. + +boot_files(Ver, Name) -> + ok = file:make_dir(filename:join([".", "releases"])), + ok = file:make_dir(filename:join([".", "releases", Ver])), + ok = file:make_symlink(filename:join(["start.boot"]), + filename:join([".", "releases", Ver, Name ++ ".boot"])), + {ok, _} = file:copy(filename:join([".", Name, "releases", Ver, "start_clean.boot"]), + filename:join([".", "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 = erl_tar:add(Tar, "lib", []), + ok = erl_tar:add(Tar, "releases", []), + ok = erl_tar:close(Tar), + ?CONSOLE("~s upgrade package created~n", [NameVer]). + +cleanup(NameVer, Name, Ver) -> + ?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"]), + filename:join([".", "relup"]) + ], + [ok = file:delete(F) || F <- Files], + + ok = remove_dir_tree("releases"), + ok = remove_dir_tree("lib"). + +%% taken 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, DirFiles} = file:list_dir(FilePath), + remove_all_files(FilePath, DirFiles), + file:del_dir(FilePath); + _ -> + file:delete(FilePath) + end + end, Files). diff --git a/test/upgrade_project/README.md b/test/upgrade_project/README.md new file mode 100644 index 0000000..cf753e8 --- /dev/null +++ b/test/upgrade_project/README.md @@ -0,0 +1,38 @@ +#### Building version 0.1 + rebar compile + rebar generate + mv rel/dummy rel/dummy_0.1 + rebar clean + # start the release: + cd rel/dummy_0.1 + bin/dummy console + + erl> dummy_server:get_state(). + erl> dummy_server:set_state(123). + erl> dummy_server:get_state(). + +#### Building version 0.2 + + # Now, in another terminal we prepare an upgrade.. + + # change release version numbers from 0.1 to 0.2 in + $EDITOR apps/dummy/src/dummy.app.src + $EDITOR rel/reltool.config + + rebar compile + rebar generate + rebar generate-upgrade previous_release=dummy_0.1 + tar -zvtf rel/dummy_0.2.tar.gz + + +#### Deploying with release_handler + mv rel/dummy_0.2.tar.gz rel/dummy_0.1/releases/ + + # Now use release_handler in the running erlang console for the deploy: + + erl> release_handler:unpack_release("dummy_0.2"). + erl> release_handler:install_release("0.2"). + erl> release_handler:make_permanent("0.2"). + + erl> release_handler:which_releases(). + erl> dummy_server:get_state(). diff --git a/test/upgrade_project/apps/dummy/ebin/dummy.appup b/test/upgrade_project/apps/dummy/ebin/dummy.appup new file mode 100644 index 0000000..e77f66f --- /dev/null +++ b/test/upgrade_project/apps/dummy/ebin/dummy.appup @@ -0,0 +1,8 @@ +{"0.2", + [{"0.1",[ + {update, dummy_server, {advanced, [foo]}} + ]}], + [{"0.1",[ + {update, dummy_server, {advanced, [foo]}} + ]}] +}. diff --git a/test/upgrade_project/apps/dummy/src/dummy.app.src b/test/upgrade_project/apps/dummy/src/dummy.app.src new file mode 100644 index 0000000..dd06752 --- /dev/null +++ b/test/upgrade_project/apps/dummy/src/dummy.app.src @@ -0,0 +1,9 @@ +{application, dummy, [ + {description, "a dummy app"}, + {vsn, "0.1"}, + {registered, [ + dummy_app + ]}, + {mod, {dummy_app, []}}, + {applications, [kernel, stdlib, sasl]} +]}. diff --git a/test/upgrade_project/apps/dummy/src/dummy_app.erl b/test/upgrade_project/apps/dummy/src/dummy_app.erl new file mode 100644 index 0000000..51363b3 --- /dev/null +++ b/test/upgrade_project/apps/dummy/src/dummy_app.erl @@ -0,0 +1,9 @@ +-module(dummy_app). +-behaviour(application). + +-export([start/2, stop/1]). + +start(_,_) -> + dummy_sup:start_link(). + +stop(_) -> ok. diff --git a/test/upgrade_project/apps/dummy/src/dummy_server.erl b/test/upgrade_project/apps/dummy/src/dummy_server.erl new file mode 100644 index 0000000..382251e --- /dev/null +++ b/test/upgrade_project/apps/dummy/src/dummy_server.erl @@ -0,0 +1,56 @@ +-module(dummy_server). +-behaviour(gen_server). + +-export([start_link/0, set_state/1, get_state/0]). + +-export([init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3]). + +%% + +start_link() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). + +set_state(What) -> + gen_server:call(?MODULE, {set_state, What}). + +get_state() -> + gen_server:call(?MODULE, get_state). + + +%% + +init([]) -> + say("init, setting state to 0", []), + {ok, 0}. + + +handle_call({set_state, NewState}, _From, _State) -> + {reply, {ok, NewState}, NewState}; + +handle_call(get_state, _From, State) -> + {reply, State, State}. + +handle_cast('__not_implemented', State) -> + {noreply, State}. + +handle_info(_Info, State) -> + say("info ~p, ~p.", [_Info, State]), + {noreply, State}. + +terminate(_Reason, _State) -> + say("terminate ~p, ~p", [_Reason, _State]), + ok. + +code_change(_OldVsn, State, _Extra) -> + say("code_change ~p, ~p, ~p", [_OldVsn, State, _Extra]), + {ok, State}. + +%% Internal + +say(Format, Data) -> + io:format("~p:~p: ~s~n", [?MODULE, self(), io_lib:format(Format, Data)]). diff --git a/test/upgrade_project/apps/dummy/src/dummy_sup.erl b/test/upgrade_project/apps/dummy/src/dummy_sup.erl new file mode 100644 index 0000000..b5617c7 --- /dev/null +++ b/test/upgrade_project/apps/dummy/src/dummy_sup.erl @@ -0,0 +1,15 @@ +-module(dummy_sup). +-behaviour(supervisor). + +-export([start_link/0]). +-export([init/1]). + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +init([]) -> + Dummy = {dummy_server, + {dummy_server, start_link, []}, + permanent, 5000, worker, [dummy_server]}, + + {ok, {{one_for_one, 10, 10}, [Dummy]}}. diff --git a/test/upgrade_project/rebar.config b/test/upgrade_project/rebar.config new file mode 100644 index 0000000..11b5b9a --- /dev/null +++ b/test/upgrade_project/rebar.config @@ -0,0 +1,4 @@ +{sub_dirs, [ + "apps/dummy", + "rel" +]}. diff --git a/test/upgrade_project/rel/files/app.config b/test/upgrade_project/rel/files/app.config new file mode 100644 index 0000000..25a3bb3 --- /dev/null +++ b/test/upgrade_project/rel/files/app.config @@ -0,0 +1,10 @@ +[ + %% SASL config + {sasl, [ + {sasl_error_logger, {file, "log/sasl-error.log"}}, + {errlog_type, error}, + {error_logger_mf_dir, "log/sasl"}, % Log directory + {error_logger_mf_maxbytes, 10485760}, % 10 MB max file size + {error_logger_mf_maxfiles, 5} % 5 files max + ]} +]. diff --git a/test/upgrade_project/rel/files/dummy b/test/upgrade_project/rel/files/dummy new file mode 100755 index 0000000..ec6d7ff --- /dev/null +++ b/test/upgrade_project/rel/files/dummy @@ -0,0 +1,155 @@ +#!/bin/bash +# -*- tab-width:4;indent-tabs-mode:nil -*- +# ex: ts=4 sw=4 et + +RUNNER_SCRIPT_DIR=$(cd ${0%/*} && pwd) + +RUNNER_BASE_DIR=${RUNNER_SCRIPT_DIR%/*} +RUNNER_ETC_DIR=$RUNNER_BASE_DIR/etc +RUNNER_LOG_DIR=$RUNNER_BASE_DIR/log +PIPE_DIR=/tmp/$RUNNER_BASE_DIR/ +RUNNER_USER= + +# Make sure this script is running as the appropriate user +if [ ! -z "$RUNNER_USER" ] && [ `whoami` != "$RUNNER_USER" ]; then + exec sudo -u $RUNNER_USER -i $0 $@ +fi + +# Make sure CWD is set to runner base dir +cd $RUNNER_BASE_DIR + +# Make sure log directory exists +mkdir -p $RUNNER_LOG_DIR + +# Extract the target node name from node.args +NAME_ARG=`grep -e '-[s]*name' $RUNNER_ETC_DIR/vm.args` +if [ -z "$NAME_ARG" ]; then + echo "vm.args needs to have either -name or -sname parameter." + exit 1 +fi + +# Extract the target cookie +COOKIE_ARG=`grep -e '-setcookie' $RUNNER_ETC_DIR/vm.args` +if [ -z "$COOKIE_ARG" ]; then + echo "vm.args needs to have a -setcookie parameter." + exit 1 +fi + +# Identify the script name +SCRIPT=`basename $0` + +# Parse out release and erts info +START_ERL=`cat $RUNNER_BASE_DIR/releases/start_erl.data` +ERTS_VSN=${START_ERL% *} +APP_VSN=${START_ERL#* } + +# Add ERTS bin dir to our path +ERTS_PATH=$RUNNER_BASE_DIR/erts-$ERTS_VSN/bin + +# Setup command to control the node +NODETOOL="$ERTS_PATH/escript $ERTS_PATH/nodetool $NAME_ARG $COOKIE_ARG" + +# Check the first argument for instructions +case "$1" in + start) + # Make sure there is not already a node running + RES=`$NODETOOL ping` + if [ "$RES" = "pong" ]; then + echo "Node is already running!" + exit 1 + fi + HEART_COMMAND="$RUNNER_BASE_DIR/bin/$SCRIPT start" + export HEART_COMMAND + mkdir -p $PIPE_DIR + # Note the trailing slash on $PIPE_DIR/ + $ERTS_PATH/run_erl -daemon $PIPE_DIR/ $RUNNER_LOG_DIR "exec $RUNNER_BASE_DIR/bin/$SCRIPT console" 2>&1 + ;; + + stop) + # Wait for the node to completely stop... + case `uname -s` in + Linux|Darwin|FreeBSD|DragonFly|NetBSD|OpenBSD) + # PID COMMAND + PID=`ps ax -o pid= -o command=|\ + grep "$RUNNER_BASE_DIR/.*/[b]eam"|awk '{print $1}'` + ;; + SunOS) + # PID COMMAND + PID=`ps -ef -o pid= -o args=|\ + grep "$RUNNER_BASE_DIR/.*/[b]eam"|awk '{print $1}'` + ;; + CYGWIN*) + # UID PID PPID TTY STIME COMMAND + PID=`ps -efW|grep "$RUNNER_BASE_DIR/.*/[b]eam"|awk '{print $2}'` + ;; + esac + $NODETOOL stop + while `kill -0 $PID 2>/dev/null`; + do + sleep 1 + done + ;; + + restart) + ## Restart the VM without exiting the process + $NODETOOL restart + ;; + + reboot) + ## Restart the VM completely (uses heart to restart it) + $NODETOOL reboot + ;; + + ping) + ## See if the VM is alive + $NODETOOL ping + ;; + + attach) + # Make sure a node IS running + RES=`$NODETOOL ping` + if [ "$RES" != "pong" ]; then + echo "Node is not running!" + exit 1 + fi + + shift + $ERTS_PATH/to_erl $PIPE_DIR + ;; + + console|console_clean) + # .boot file typically just $SCRIPT (ie, the app name) + # however, for debugging, sometimes start_clean.boot is useful: + case "$1" in + console) BOOTFILE=$SCRIPT ;; + console_clean) BOOTFILE=start_clean ;; + esac + # Setup beam-required vars + ROOTDIR=$RUNNER_BASE_DIR + BINDIR=$ROOTDIR/erts-$ERTS_VSN/bin + EMU=beam + PROGNAME=`echo $0 | sed 's/.*\\///'` + CMD="$BINDIR/erlexec -boot $RUNNER_BASE_DIR/releases/$APP_VSN/$BOOTFILE -embedded -config $RUNNER_ETC_DIR/app.config -args_file $RUNNER_ETC_DIR/vm.args -- ${1+"$@"}" + export EMU + export ROOTDIR + export BINDIR + export PROGNAME + + # Dump environment info for logging purposes + echo "Exec: $CMD" + echo "Root: $ROOTDIR" + + # Log the startup + logger -t "$SCRIPT[$$]" "Starting up" + + # Start the VM + exec $CMD + ;; + + *) + echo "Usage: $SCRIPT {start|stop|restart|reboot|ping|console|attach}" + exit 1 + ;; +esac + +exit 0 diff --git a/test/upgrade_project/rel/files/erl b/test/upgrade_project/rel/files/erl new file mode 100755 index 0000000..b985f23 --- /dev/null +++ b/test/upgrade_project/rel/files/erl @@ -0,0 +1,34 @@ +#!/bin/bash + +## This script replaces the default "erl" in erts-VSN/bin. This is necessary +## as escript depends on erl and in turn, erl depends on having access to a +## bootscript (start.boot). Note that this script is ONLY invoked as a side-effect +## of running escript -- the embedded node bypasses erl and uses erlexec directly +## (as it should). +## +## Note that this script makes the assumption that there is a start_clean.boot +## file available in $ROOTDIR/release/VSN. + +# Determine the abspath of where this script is executing from. +ERTS_BIN_DIR=$(cd ${0%/*} && pwd) + +# Now determine the root directory -- this script runs from erts-VSN/bin, +# so we simply need to strip off two dirs from the end of the ERTS_BIN_DIR +# path. +ROOTDIR=${ERTS_BIN_DIR%/*/*} + +# Parse out release and erts info +START_ERL=`cat $ROOTDIR/releases/start_erl.data` +ERTS_VSN=${START_ERL% *} +APP_VSN=${START_ERL#* } + +BINDIR=$ROOTDIR/erts-$ERTS_VSN/bin +EMU=beam +PROGNAME=`echo $0 | sed 's/.*\\///'` +CMD="$BINDIR/erlexec" +export EMU +export ROOTDIR +export BINDIR +export PROGNAME + +exec $CMD -boot $ROOTDIR/releases/$APP_VSN/start_clean ${1+"$@"} diff --git a/test/upgrade_project/rel/files/nodetool b/test/upgrade_project/rel/files/nodetool new file mode 100755 index 0000000..cb524ce --- /dev/null +++ b/test/upgrade_project/rel/files/nodetool @@ -0,0 +1,116 @@ +%% -*- mode:erlang;tab-width:4;erlang-indent-level:4;indent-tabs-mode:nil -*- +%% ex: ft=erlang ts=4 sw=4 et +%% ------------------------------------------------------------------- +%% +%% nodetool: Helper Script for interacting with live nodes +%% +%% ------------------------------------------------------------------- + +main(Args) -> + %% Extract the args + {RestArgs, TargetNode} = process_args(Args, [], undefined), + + %% See if the node is currently running -- if it's not, we'll bail + case {net_kernel:hidden_connect_node(TargetNode), net_adm:ping(TargetNode)} of + {true, pong} -> + ok; + {_, pang} -> + io:format("Node ~p not responding to pings.\n", [TargetNode]), + halt(1) + end, + + case RestArgs of + ["ping"] -> + %% If we got this far, the node already responsed to a ping, so just dump + %% a "pong" + io:format("pong\n"); + ["stop"] -> + io:format("~p\n", [rpc:call(TargetNode, init, stop, [], 60000)]); + ["restart"] -> + io:format("~p\n", [rpc:call(TargetNode, init, restart, [], 60000)]); + ["reboot"] -> + io:format("~p\n", [rpc:call(TargetNode, init, reboot, [], 60000)]); + ["rpc", Module, Function | RpcArgs] -> + case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function), + [RpcArgs], 60000) of + ok -> + ok; + {badrpc, Reason} -> + io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]), + halt(1); + _ -> + halt(1) + end; + ["rpcterms", Module, Function, ArgsAsString] -> + case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function), + consult(ArgsAsString), 60000) of + {badrpc, Reason} -> + io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]), + halt(1); + Other -> + io:format("~p\n", [Other]) + end; + Other -> + io:format("Other: ~p\n", [Other]), + io:format("Usage: nodetool {ping|stop|restart|reboot}\n") + end, + net_kernel:stop(). + +process_args([], Acc, TargetNode) -> + {lists:reverse(Acc), TargetNode}; +process_args(["-setcookie", Cookie | Rest], Acc, TargetNode) -> + erlang:set_cookie(node(), list_to_atom(Cookie)), + process_args(Rest, Acc, TargetNode); +process_args(["-name", TargetName | Rest], Acc, _) -> + ThisNode = append_node_suffix(TargetName, "_maint_"), + {ok, _} = net_kernel:start([ThisNode, longnames]), + process_args(Rest, Acc, nodename(TargetName)); +process_args(["-sname", TargetName | Rest], Acc, _) -> + ThisNode = append_node_suffix(TargetName, "_maint_"), + {ok, _} = net_kernel:start([ThisNode, shortnames]), + process_args(Rest, Acc, nodename(TargetName)); +process_args([Arg | Rest], Acc, Opts) -> + process_args(Rest, [Arg | Acc], Opts). + + +nodename(Name) -> + case string:tokens(Name, "@") of + [_Node, _Host] -> + list_to_atom(Name); + [Node] -> + [_, Host] = string:tokens(atom_to_list(node()), "@"), + list_to_atom(lists:concat([Node, "@", Host])) + end. + +append_node_suffix(Name, Suffix) -> + case string:tokens(Name, "@") of + [Node, Host] -> + list_to_atom(lists:concat([Node, Suffix, os:getpid(), "@", Host])); + [Node] -> + list_to_atom(lists:concat([Node, Suffix, os:getpid()])) + end. + + +%% +%% Given a string or binary, parse it into a list of terms, ala file:consult/0 +%% +consult(Str) when is_list(Str) -> + consult([], Str, []); +consult(Bin) when is_binary(Bin)-> + consult([], binary_to_list(Bin), []). + +consult(Cont, Str, Acc) -> + case erl_scan:tokens(Cont, Str, 0) of + {done, Result, Remaining} -> + case Result of + {ok, Tokens, _} -> + {ok, Term} = erl_parse:parse_term(Tokens), + consult([], Remaining, [Term | Acc]); + {eof, _Other} -> + lists:reverse(Acc); + {error, Info, _} -> + {error, Info} + end; + {more, Cont1} -> + consult(Cont1, eof, Acc) + end. diff --git a/test/upgrade_project/rel/files/vm.args b/test/upgrade_project/rel/files/vm.args new file mode 100644 index 0000000..7448fb1 --- /dev/null +++ b/test/upgrade_project/rel/files/vm.args @@ -0,0 +1,20 @@ + +## Name of the node +-name dummy@127.0.0.1 + +## Cookie for distributed erlang +-setcookie dummy + +## Heartbeat management; auto-restarts VM if it dies or becomes unresponsive +## (Disabled by default..use with caution!) +##-heart + +## Enable kernel poll and a few async threads ++K true ++A 5 + +## Increase number of concurrent ports/sockets +-env ERL_MAX_PORTS 4096 + +## Tweak GC to run more often +-env ERL_FULLSWEEP_AFTER 10 diff --git a/test/upgrade_project/rel/reltool.config b/test/upgrade_project/rel/reltool.config new file mode 100644 index 0000000..22cec5e --- /dev/null +++ b/test/upgrade_project/rel/reltool.config @@ -0,0 +1,25 @@ +{sys, [ + {lib_dirs, ["../apps"]}, + {rel, "dummy", "0.1", [ + kernel, + stdlib, + sasl, + dummy + ]}, + {rel, "start_clean", "", [kernel, stdlib]}, + {boot_rel, "dummy"}, + {profile, embedded}, + {excl_sys_filters, ["^bin/.*", "^erts.*/bin/(dialyzer|typer)"]}, + {excl_archive_filters, [".*"]}, + + {app, dummy, [{incl_cond, include}]} +]}. + +{overlay, [ + {mkdir, "log/sasl"}, + {copy, "files/erl", "{{erts_vsn}}/bin/erl"}, + {copy, "files/nodetool", "{{erts_vsn}}/bin/nodetool"}, + {copy, "files/dummy", "bin/dummy"}, + {copy, "files/app.config", "etc/app.config"}, + {copy, "files/vm.args", "etc/vm.args"} + ]}. -- cgit v1.1 From e53873f549e68514565e9d369e3972f8ec9cc396 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Thu, 27 Jan 2011 18:24:57 +0100 Subject: Update THANKS file --- THANKS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/THANKS b/THANKS index 85c40bf..607e4e2 100644 --- a/THANKS +++ b/THANKS @@ -37,3 +37,7 @@ Magnus Klaar Anthony Ramine Charles McKnight Andrew Tunnell-Jones +Joe Williams +Daniel Reverri +Jesper Louis Andersen +Richard Jones -- cgit v1.1 From 8f5bfea9c479d05298780ec51e1ab3b0f8af42cc Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 28 Jan 2011 19:05:20 +0100 Subject: Fix help: previous_release is mandatory --- src/rebar.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rebar.erl b/src/rebar.erl index 6c99ab5..e84fb44 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -211,7 +211,7 @@ delete-deps Delete fetched dependencies generate [dump_spec=0/1] Build release with reltool -generate-upgrade [previous_release=path] Build an upgrade package +generate-upgrade previous_release=path Build an upgrade package eunit [suite=foo] Run eunit [test/foo_tests.erl] tests ct [suite=] [case=] Run common_test suites in ./test -- cgit v1.1 From f4070bfad7a62c12207ad97935567255a3854593 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 28 Jan 2011 19:10:19 +0100 Subject: Update shell completion: generate-upgrade Add generate-upgrade and previous_release=. --- priv/shell-completion/bash/rebar | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/priv/shell-completion/bash/rebar b/priv/shell-completion/bash/rebar index ead10ff..581ec0d 100644 --- a/priv/shell-completion/bash/rebar +++ b/priv/shell-completion/bash/rebar @@ -10,9 +10,9 @@ _rebar() lopts=" --help --commands --verbose --force --jobs= --version" cmdsnvars="build-plt check-plt check-deps clean compile \ create create-app create-node ct dialyze doc delete-deps eunit \ - get-deps generate help list-templates update-deps version xref \ - case= debug_info=1 force=1 jobs= suite= verbose=1 appid= \ - skip_deps=1 template= template_dir=" + get-deps generate generate-upgrade help list-templates update-deps \ + version xref case= debug_info=1 force=1 jobs= suite= verbose=1 \ + appid= previous_release= skip_deps=1 template= template_dir=" if [[ ${cur} == --* ]] ; then COMPREPLY=( $(compgen -W "${lopts}" -- ${cur}) ) -- cgit v1.1 From 926baa1c31940ba49bd8a798fe4a4efecb636420 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 28 Jan 2011 20:02:51 +0100 Subject: Use filename:join instead of ?FMT --- src/rebar_port_compiler.erl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl index e684042..32dfa41 100644 --- a/src/rebar_port_compiler.erl +++ b/src/rebar_port_compiler.erl @@ -385,16 +385,18 @@ make_so_specs(Config, AppFile, Bins) -> undefined -> %% New form of so_specs is not provided. See if the old form of {so_name} is available %% instead + Dir = "priv", SoName = case rebar_config:get(Config, so_name, undefined) of undefined -> %% Ok, neither old nor new form is available. Use the app name and %% generate a sensible default. AppName = rebar_app_utils:app_name(AppFile), - ?FMT("priv/~s", [lists:concat([AppName, "_drv.so"])]); + filename:join(Dir, + lists:concat([AppName, "_drv.so"])); AName -> %% Old form is available -- use it - ?FMT("priv/~s", [AName]) + filename:join(Dir, AName) end, [{SoName, Bins}]; -- cgit v1.1 From b894682ba92baa0f258908cf5dacb5ec0cd14635 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Thu, 20 Jan 2011 18:56:42 +0100 Subject: Fix bug 294 --- priv/templates/simplenode.nodetool | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/priv/templates/simplenode.nodetool b/priv/templates/simplenode.nodetool index cb524ce..0318ca1 100644 --- a/priv/templates/simplenode.nodetool +++ b/priv/templates/simplenode.nodetool @@ -7,6 +7,7 @@ %% ------------------------------------------------------------------- main(Args) -> + ok = start_epmd(), %% Extract the args {RestArgs, TargetNode} = process_args(Args, [], undefined), @@ -73,6 +74,27 @@ process_args([Arg | Rest], Acc, Opts) -> process_args(Rest, [Arg | Acc], Opts). +start_epmd() -> + [] = os:cmd(epmd_path() ++ " -daemon"), + ok. + +epmd_path() -> + ErtsBinDir = filename:dirname(escript:script_name()), + Name = "epmd", + case os:find_executable(Name, ErtsBinDir) of + false -> + case os:find_executable(Name) of + false -> + io:format("Could not find epmd.~n"), + halt(1); + GlobalEpmd -> + GlobalEpmd + end; + Epmd -> + Epmd + end. + + nodename(Name) -> case string:tokens(Name, "@") of [_Node, _Host] -> -- cgit v1.1 From 7ac3a5aa9b03e8e1a1c5b3d8fcdfeedd6819c074 Mon Sep 17 00:00:00 2001 From: Tim Watson Date: Wed, 26 Jan 2011 02:15:27 +0000 Subject: Move BUILD_TIME and VCS_INFO macros I have moved these macros from rebar_core.erl to rebar.erl in order to prevent eunit tests from failing (which they currently are). --- src/rebar.erl | 8 ++++++++ src/rebar_core.erl | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/rebar.erl b/src/rebar.erl index e84fb44..554278e 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -33,6 +33,14 @@ -include("rebar.hrl"). +-ifndef(BUILD_TIME). +-define(BUILD_TIME, "undefined"). +-endif. + +-ifndef(VCS_INFO). +-define(VCS_INFO, "undefined"). +-endif. + %% ==================================================================== %% Public API %% ==================================================================== diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 1c3940f..954e6b8 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -34,14 +34,6 @@ -include("rebar.hrl"). --ifndef(BUILD_TIME). --define(BUILD_TIME, "undefined"). --endif. - --ifndef(VCS_INFO). --define(VCS_INFO, "undefined"). --endif. - %% =================================================================== %% Public API %% =================================================================== -- cgit v1.1 From 0e729bf90e64a00bd8915e227d83f82877038e9e Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sat, 29 Jan 2011 15:50:24 +0100 Subject: Fix Dialyzer warnings in rebar_upgrade --- src/rebar_upgrade.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rebar_upgrade.erl b/src/rebar_upgrade.erl index 4c0d2f7..0026cee 100644 --- a/src/rebar_upgrade.erl +++ b/src/rebar_upgrade.erl @@ -54,7 +54,7 @@ run_systools(NameVer, NewName), %% Boot file changes - boot_files(NewVer, NewName), + {ok, _} = boot_files(NewVer, NewName), %% Extract upgrade and tar it back up with changes make_tar(NameVer), @@ -183,7 +183,7 @@ cleanup(NameVer, Name, Ver) -> filename:join([".", NameVer ++ ".script"]), filename:join([".", "relup"]) ], - [ok = file:delete(F) || F <- Files], + lists:foreach(fun(F) -> ok = file:delete(F) end, Files), ok = remove_dir_tree("releases"), ok = remove_dir_tree("lib"). -- cgit v1.1 From b18194e24d9b764bcd912ac87c2132a6c3866a21 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sat, 29 Jan 2011 17:37:15 +0100 Subject: Fix file existence checks --- inttest/tdeps1/tdeps1_rt.erl | 2 +- test/rebar_eunit_tests.erl | 6 +++--- test/rebar_file_utils_tests.erl | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/inttest/tdeps1/tdeps1_rt.erl b/inttest/tdeps1/tdeps1_rt.erl index 5eb831d..690e273 100644 --- a/inttest/tdeps1/tdeps1_rt.erl +++ b/inttest/tdeps1/tdeps1_rt.erl @@ -33,7 +33,7 @@ run(Dir) -> {ok, _} = retest_sh:run("./rebar get-deps compile", []), - true = filelib:is_file("ebin/a.beam"), + true = filelib:is_regular("ebin/a.beam"), ok. diff --git a/test/rebar_eunit_tests.erl b/test/rebar_eunit_tests.erl index 4179c9b..acd21f2 100644 --- a/test/rebar_eunit_tests.erl +++ b/test/rebar_eunit_tests.erl @@ -119,7 +119,7 @@ environment_test_() -> ?_assert(filelib:is_dir(?TMP_DIR))}, {"Ensure the rebar script can be found, copied, and run", - [?_assert(filelib:is_file(?REBAR_SCRIPT)), + [?_assert(filelib:is_regular(?REBAR_SCRIPT)), fun assert_rebar_runs/0]}]}. assert_rebar_runs() -> @@ -236,12 +236,12 @@ assert_dirs_in(Name, [Dir|T]) -> assert_dirs_in(_, []) -> []. assert_files_in(Name, [File|T]) -> - [{Name ++ " has file: " ++ File, ?_assert(filelib:is_file(File))} | + [{Name ++ " has file: " ++ File, ?_assert(filelib:is_regular(File))} | assert_files_in(Name, T)]; assert_files_in(_, []) -> []. assert_files_not_in(Name, [File|T]) -> - [{Name ++ " does not have file: " ++ File, ?_assertNot(filelib:is_file(File))} | + [{Name ++ " does not have file: " ++ File, ?_assertNot(filelib:is_regular(File))} | assert_files_not_in(Name, T)]; assert_files_not_in(_, []) -> []. diff --git a/test/rebar_file_utils_tests.erl b/test/rebar_file_utils_tests.erl index fd9a141..832cc64 100644 --- a/test/rebar_file_utils_tests.erl +++ b/test/rebar_file_utils_tests.erl @@ -96,7 +96,7 @@ cp_r_file_to_file_test_() -> filename:join([?TMP_DIR,"dest","new_file"])) end, fun teardown/1, - [?_assert(filelib:is_file(filename:join([?TMP_DIR,"dest","new_file"])))]}. + [?_assert(filelib:is_regular(filename:join([?TMP_DIR,"dest","new_file"])))]}. cp_r_file_to_dir_test_() -> {"cp_r copies a file to directory", @@ -107,7 +107,7 @@ cp_r_file_to_dir_test_() -> filename:join([?TMP_DIR,"dest"])) end, fun teardown/1, - [?_assert(filelib:is_file(filename:join([?TMP_DIR,"dest","file1"])))]}. + [?_assert(filelib:is_regular(filename:join([?TMP_DIR,"dest","file1"])))]}. cp_r_dir_to_dir_test_() -> {"cp_r copies a directory to directory", @@ -132,7 +132,7 @@ cp_r_wildcard_file_to_dir_test_() -> filename:join([?TMP_DIR,"dest"])) end, fun teardown/1, - [?_assert(filelib:is_file(filename:join([?TMP_DIR,"dest","file1"])))]}. + [?_assert(filelib:is_regular(filename:join([?TMP_DIR,"dest","file1"])))]}. cp_r_wildcard_dir_to_dir_test_() -> {"cp_r copies wildcard directory to directory", @@ -224,8 +224,8 @@ mv_file_test_() -> filename:join([?TMP_DIR,"dest"])) end, fun teardown/1, - [?_assert(filelib:is_file(filename:join([?TMP_DIR,"dest","file1"]))), - ?_assertNot(filelib:is_file(filename:join([?TMP_DIR,"source","file1"])))]}. + [?_assert(filelib:is_regular(filename:join([?TMP_DIR,"dest","file1"]))), + ?_assertNot(filelib:is_regular(filename:join([?TMP_DIR,"source","file1"])))]}. %% ==================================================================== %% Utilities @@ -266,12 +266,12 @@ teardown(_) -> %% ==================================================================== assert_files_in(Name, [File|T]) -> - [{Name ++ " has file: " ++ File, ?_assert(filelib:is_file(File))} | + [{Name ++ " has file: " ++ File, ?_assert(filelib:is_regular(File))} | assert_files_in(Name, T)]; assert_files_in(_, []) -> []. assert_files_not_in(Name, [File|T]) -> [{Name ++ " does not have file: " ++ File, - ?_assertNot(filelib:is_file(File))} | + ?_assertNot(filelib:is_regular(File))} | assert_files_not_in(Name, T)]; assert_files_not_in(_, []) -> []. -- cgit v1.1 From f04a1c9750bc196aafbb2931579db38624e68535 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sun, 30 Jan 2011 17:54:07 +0100 Subject: Add Tim Watson to THANKS file --- THANKS | 1 + 1 file changed, 1 insertion(+) diff --git a/THANKS b/THANKS index 607e4e2..0e40965 100644 --- a/THANKS +++ b/THANKS @@ -41,3 +41,4 @@ Joe Williams Daniel Reverri Jesper Louis Andersen Richard Jones +Tim Watson -- cgit v1.1 From 1ee21c523fdf96d93f6d6a1f48ac6944ed5e47cf Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Mon, 31 Jan 2011 17:55:02 +0100 Subject: Update nodetool in upgrade_project --- test/upgrade_project/rel/files/nodetool | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) mode change 100755 => 100644 test/upgrade_project/rel/files/nodetool diff --git a/test/upgrade_project/rel/files/nodetool b/test/upgrade_project/rel/files/nodetool old mode 100755 new mode 100644 index cb524ce..0318ca1 --- a/test/upgrade_project/rel/files/nodetool +++ b/test/upgrade_project/rel/files/nodetool @@ -7,6 +7,7 @@ %% ------------------------------------------------------------------- main(Args) -> + ok = start_epmd(), %% Extract the args {RestArgs, TargetNode} = process_args(Args, [], undefined), @@ -73,6 +74,27 @@ process_args([Arg | Rest], Acc, Opts) -> process_args(Rest, [Arg | Acc], Opts). +start_epmd() -> + [] = os:cmd(epmd_path() ++ " -daemon"), + ok. + +epmd_path() -> + ErtsBinDir = filename:dirname(escript:script_name()), + Name = "epmd", + case os:find_executable(Name, ErtsBinDir) of + false -> + case os:find_executable(Name) of + false -> + io:format("Could not find epmd.~n"), + halt(1); + GlobalEpmd -> + GlobalEpmd + end; + Epmd -> + Epmd + end. + + nodename(Name) -> case string:tokens(Name, "@") of [_Node, _Host] -> -- cgit v1.1 From c466076ffb5a1ea4c00d49fefff0dcfbceb58236 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Mon, 31 Jan 2011 17:43:31 +0100 Subject: Clean up emacs file local variables --- bootstrap | 2 +- inttest/rgen1/reltool.config | 2 +- priv/templates/simplenode.nodetool | 2 +- rebar.config.sample | 2 +- src/rebar.erl | 2 +- src/rebar_abnfc_compiler.erl | 2 +- src/rebar_app_utils.erl | 2 +- src/rebar_asn1_compiler.erl | 2 +- src/rebar_base_compiler.erl | 2 +- src/rebar_cleaner.erl | 2 +- src/rebar_config.erl | 2 +- src/rebar_core.erl | 2 +- src/rebar_ct.erl | 2 +- src/rebar_deps.erl | 2 +- src/rebar_dialyzer.erl | 2 +- src/rebar_edoc.erl | 2 +- src/rebar_erlc_compiler.erl | 2 +- src/rebar_erlydtl_compiler.erl | 2 +- src/rebar_escripter.erl | 2 +- src/rebar_eunit.erl | 2 +- src/rebar_file_utils.erl | 2 +- src/rebar_lfe_compiler.erl | 2 +- src/rebar_log.erl | 2 +- src/rebar_neotoma_compiler.erl | 2 +- src/rebar_otp_app.erl | 2 +- src/rebar_port_compiler.erl | 2 +- src/rebar_post_script.erl | 2 +- src/rebar_pre_script.erl | 2 +- src/rebar_protobuffs_compiler.erl | 2 +- src/rebar_rel_utils.erl | 2 +- src/rebar_reltool.erl | 2 +- src/rebar_require_vsn.erl | 2 +- src/rebar_subdirs.erl | 2 +- src/rebar_templater.erl | 2 +- src/rebar_upgrade.erl | 2 +- src/rebar_utils.erl | 2 +- src/rebar_xref.erl | 2 +- test/rebar_eunit_tests.erl | 2 +- test/rebar_file_utils_tests.erl | 2 +- test/upgrade_project/rel/files/nodetool | 2 +- 40 files changed, 40 insertions(+), 40 deletions(-) diff --git a/bootstrap b/bootstrap index c30c6dc..f779fb3 100755 --- a/bootstrap +++ b/bootstrap @@ -1,5 +1,5 @@ #!/usr/bin/env escript -%% -*- mode:erlang;tab-width:4;erlang-indent-level:4;indent-tabs-mode:nil -*- +%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ft=erlang ts=4 sw=4 et main(Args) -> diff --git a/inttest/rgen1/reltool.config b/inttest/rgen1/reltool.config index c6e31f5..4c4713c 100644 --- a/inttest/rgen1/reltool.config +++ b/inttest/rgen1/reltool.config @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et {sys, [ {rel, "rgen1", "0.1", diff --git a/priv/templates/simplenode.nodetool b/priv/templates/simplenode.nodetool index 0318ca1..eb08fa4 100644 --- a/priv/templates/simplenode.nodetool +++ b/priv/templates/simplenode.nodetool @@ -1,4 +1,4 @@ -%% -*- mode:erlang;tab-width:4;erlang-indent-level:4;indent-tabs-mode:nil -*- +%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ft=erlang ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/rebar.config.sample b/rebar.config.sample index ea3fdc4..8954c15 100644 --- a/rebar.config.sample +++ b/rebar.config.sample @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 ft=erlang et %% This is a sample rebar.conf file that shows examples of some of rebar's %% options. diff --git a/src/rebar.erl b/src/rebar.erl index 554278e..d9e302a 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_abnfc_compiler.erl b/src/rebar_abnfc_compiler.erl index 743b3fe..80fdf5e 100644 --- a/src/rebar_abnfc_compiler.erl +++ b/src/rebar_abnfc_compiler.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl index ea8e079..1fa870b 100644 --- a/src/rebar_app_utils.erl +++ b/src/rebar_app_utils.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_asn1_compiler.erl b/src/rebar_asn1_compiler.erl index 39614f0..750ff41 100644 --- a/src/rebar_asn1_compiler.erl +++ b/src/rebar_asn1_compiler.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_base_compiler.erl b/src/rebar_base_compiler.erl index aea55df..341957c 100644 --- a/src/rebar_base_compiler.erl +++ b/src/rebar_base_compiler.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_cleaner.erl b/src/rebar_cleaner.erl index 2ff828e..9ddeb8a 100644 --- a/src/rebar_cleaner.erl +++ b/src/rebar_cleaner.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_config.erl b/src/rebar_config.erl index 7da6900..a030e2c 100644 --- a/src/rebar_config.erl +++ b/src/rebar_config.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 954e6b8..5a6bebd 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_ct.erl b/src/rebar_ct.erl index 74399ee..a7fc889 100644 --- a/src/rebar_ct.erl +++ b/src/rebar_ct.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl index d93b158..8f31d0f 100644 --- a/src/rebar_deps.erl +++ b/src/rebar_deps.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_dialyzer.erl b/src/rebar_dialyzer.erl index acaf69a..ea2bd49 100644 --- a/src/rebar_dialyzer.erl +++ b/src/rebar_dialyzer.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_edoc.erl b/src/rebar_edoc.erl index dd7e779..8a0b7a5 100644 --- a/src/rebar_edoc.erl +++ b/src/rebar_edoc.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 0166c09..14dd4df 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_erlydtl_compiler.erl b/src/rebar_erlydtl_compiler.erl index 35a548d..654fd74 100644 --- a/src/rebar_erlydtl_compiler.erl +++ b/src/rebar_erlydtl_compiler.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_escripter.erl b/src/rebar_escripter.erl index 20f5e66..5ee95e9 100644 --- a/src/rebar_escripter.erl +++ b/src/rebar_escripter.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl index f1ddead..a05afd3 100644 --- a/src/rebar_eunit.erl +++ b/src/rebar_eunit.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_file_utils.erl b/src/rebar_file_utils.erl index 026b06b..1e8e523 100644 --- a/src/rebar_file_utils.erl +++ b/src/rebar_file_utils.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_lfe_compiler.erl b/src/rebar_lfe_compiler.erl index 4451530..d5b6e76 100644 --- a/src/rebar_lfe_compiler.erl +++ b/src/rebar_lfe_compiler.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_log.erl b/src/rebar_log.erl index dba59fe..3dde0b5 100644 --- a/src/rebar_log.erl +++ b/src/rebar_log.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_neotoma_compiler.erl b/src/rebar_neotoma_compiler.erl index e46caf4..4301323 100644 --- a/src/rebar_neotoma_compiler.erl +++ b/src/rebar_neotoma_compiler.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl index 7cb70df..af579d9 100644 --- a/src/rebar_otp_app.erl +++ b/src/rebar_otp_app.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl index 32dfa41..c8c1cbd 100644 --- a/src/rebar_port_compiler.erl +++ b/src/rebar_port_compiler.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_post_script.erl b/src/rebar_post_script.erl index d83df1c..c7f2d01 100644 --- a/src/rebar_post_script.erl +++ b/src/rebar_post_script.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_pre_script.erl b/src/rebar_pre_script.erl index 5b8fecd..9097807 100644 --- a/src/rebar_pre_script.erl +++ b/src/rebar_pre_script.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_protobuffs_compiler.erl b/src/rebar_protobuffs_compiler.erl index eafed41..8ad0318 100644 --- a/src/rebar_protobuffs_compiler.erl +++ b/src/rebar_protobuffs_compiler.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_rel_utils.erl b/src/rebar_rel_utils.erl index 978f9d6..91031e8 100644 --- a/src/rebar_rel_utils.erl +++ b/src/rebar_rel_utils.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_reltool.erl b/src/rebar_reltool.erl index d375e97..dc19538 100644 --- a/src/rebar_reltool.erl +++ b/src/rebar_reltool.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_require_vsn.erl b/src/rebar_require_vsn.erl index be51be9..0f428a1 100644 --- a/src/rebar_require_vsn.erl +++ b/src/rebar_require_vsn.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_subdirs.erl b/src/rebar_subdirs.erl index 7e39ffa..abae853 100644 --- a/src/rebar_subdirs.erl +++ b/src/rebar_subdirs.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl index 5a02511..7716066 100644 --- a/src/rebar_templater.erl +++ b/src/rebar_templater.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_upgrade.erl b/src/rebar_upgrade.erl index 0026cee..c882cc8 100644 --- a/src/rebar_upgrade.erl +++ b/src/rebar_upgrade.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index a9ed9a0..aa324c2 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/src/rebar_xref.erl b/src/rebar_xref.erl index 05bb46b..8a489a8 100644 --- a/src/rebar_xref.erl +++ b/src/rebar_xref.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/test/rebar_eunit_tests.erl b/test/rebar_eunit_tests.erl index acd21f2..57a337a 100644 --- a/test/rebar_eunit_tests.erl +++ b/test/rebar_eunit_tests.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/test/rebar_file_utils_tests.erl b/test/rebar_file_utils_tests.erl index 832cc64..ea8ccf9 100644 --- a/test/rebar_file_utils_tests.erl +++ b/test/rebar_file_utils_tests.erl @@ -1,4 +1,4 @@ -%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et %% ------------------------------------------------------------------- %% diff --git a/test/upgrade_project/rel/files/nodetool b/test/upgrade_project/rel/files/nodetool index 0318ca1..eb08fa4 100644 --- a/test/upgrade_project/rel/files/nodetool +++ b/test/upgrade_project/rel/files/nodetool @@ -1,4 +1,4 @@ -%% -*- mode:erlang;tab-width:4;erlang-indent-level:4;indent-tabs-mode:nil -*- +%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ft=erlang ts=4 sw=4 et %% ------------------------------------------------------------------- %% -- cgit v1.1 From 7710ab0d9f5be0833179d08d6eeb5da53ac1ed36 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Mon, 31 Jan 2011 19:11:50 +0100 Subject: Fix warning --- inttest/tdeps1/tdeps1_rt.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inttest/tdeps1/tdeps1_rt.erl b/inttest/tdeps1/tdeps1_rt.erl index 690e273..9072e9c 100644 --- a/inttest/tdeps1/tdeps1_rt.erl +++ b/inttest/tdeps1/tdeps1_rt.erl @@ -23,7 +23,7 @@ files() -> {copy, "c.hrl", "repo/c/include/c.hrl"} ]. -run(Dir) -> +run(_Dir) -> %% Initialize the b/c apps as mercurial repos so that dependencies pull %% properly HgCmd = "/bin/sh -c \"hg init && hg add && hg commit -m 'Initial commit'\"", -- cgit v1.1 From 63de05d914f3c2bef6dcfc6cf966400d93c9c80d Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 28 Jan 2011 16:08:27 +0100 Subject: Clean up code --- src/rebar.erl | 29 ++++---- src/rebar_abnfc_compiler.erl | 14 ++-- src/rebar_base_compiler.erl | 6 +- src/rebar_core.erl | 40 ++++++----- src/rebar_ct.erl | 27 +++---- src/rebar_deps.erl | 51 ++++++++------ src/rebar_dialyzer.erl | 36 +++++----- src/rebar_edoc.erl | 6 +- src/rebar_erlc_compiler.erl | 110 ++++++++++++++++------------- src/rebar_erlydtl_compiler.erl | 20 +++--- src/rebar_escripter.erl | 15 ++-- src/rebar_eunit.erl | 66 ++++++++++------- src/rebar_file_utils.erl | 6 +- src/rebar_lfe_compiler.erl | 13 ++-- src/rebar_log.erl | 3 - src/rebar_neotoma_compiler.erl | 54 +++++++------- src/rebar_otp_app.erl | 54 ++++++++------ src/rebar_port_compiler.erl | 144 ++++++++++++++++++++++---------------- src/rebar_protobuffs_compiler.erl | 21 +++--- src/rebar_reltool.erl | 44 +++++++----- src/rebar_require_vsn.erl | 3 - src/rebar_subdirs.erl | 4 +- src/rebar_templater.erl | 87 ++++++++++++++--------- src/rebar_upgrade.erl | 10 +-- src/rebar_utils.erl | 2 +- src/rebar_xref.erl | 43 +++++++----- 26 files changed, 523 insertions(+), 385 deletions(-) diff --git a/src/rebar.erl b/src/rebar.erl index d9e302a..22f2080 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -52,7 +52,8 @@ main(Args) -> {error, failed} -> halt(1); Error -> - %% Nothing should percolate up from rebar_core; dump this error to console + %% Nothing should percolate up from rebar_core; + %% Dump this error to console io:format("Uncaught error in rebar_core: ~p\n", [Error]), halt(1) end. @@ -88,7 +89,8 @@ run_aux(Commands) -> %% Determine the location of the rebar executable; important for pulling %% resources out of the escript rebar_config:set_global(escript, filename:absname(escript:script_name())), - ?DEBUG("Rebar location: ~p\n", [rebar_config:get_global(escript, undefined)]), + ?DEBUG("Rebar location: ~p\n", + [rebar_config:get_global(escript, undefined)]), %% Note the top-level directory for reference rebar_config:set_global(base_dir, filename:absname(rebar_utils:get_cwd())), @@ -153,7 +155,8 @@ parse_args(Args) -> %% version() -> {ok, Vsn} = application:get_key(rebar, vsn), - ?CONSOLE("rebar version: ~s date: ~s vcs: ~s\n", [Vsn, ?BUILD_TIME, ?VCS_INFO]). + ?CONSOLE("rebar version: ~s date: ~s vcs: ~s\n", + [Vsn, ?BUILD_TIME, ?VCS_INFO]). %% @@ -239,17 +242,17 @@ version Show version information option_spec_list() -> Jobs = rebar_config:get_jobs(), JobsHelp = io_lib:format( - "Number of concurrent workers a command may use. Default: ~B", - [Jobs]), + "Number of concurrent workers a command may use. Default: ~B", + [Jobs]), [ %% {Name, ShortOpt, LongOpt, ArgSpec, HelpMsg} - {help, $h, "help", undefined, "Show the program options"}, - {commands, $c, "commands", undefined, "Show available commands"}, - {verbose, $v, "verbose", undefined, "Be verbose about what gets done"}, - {version, $V, "version", undefined, "Show version information"}, - {force, $f, "force", undefined, "Force"}, - {jobs, $j, "jobs", integer, JobsHelp}, - {config, $C, "config", string, "Rebar config file to use"} + {help, $h, "help", undefined, "Show the program options"}, + {commands, $c, "commands", undefined, "Show available commands"}, + {verbose, $v, "verbose", undefined, "Be verbose about what gets done"}, + {version, $V, "version", undefined, "Show version information"}, + {force, $f, "force", undefined, "Force"}, + {jobs, $j, "jobs", integer, JobsHelp}, + {config, $C, "config", string, "Rebar config file to use"} ]. %% @@ -303,7 +306,7 @@ get_command_name_candidates(Command) -> %% * "create-a" matches create-app %% * "c-app" matches create-app Candidates = [Candidate || Candidate <- command_names(), - is_command_name_candidate(Command, Candidate)], + is_command_name_candidate(Command, Candidate)], %% Is there a complete match? If so return only that, return a %% list of candidates otherwise case lists:member(Command, Candidates) of diff --git a/src/rebar_abnfc_compiler.erl b/src/rebar_abnfc_compiler.erl index 80fdf5e..bfb9a35 100644 --- a/src/rebar_abnfc_compiler.erl +++ b/src/rebar_abnfc_compiler.erl @@ -85,12 +85,12 @@ compile_abnfc(Source, _Target, Config) -> case abnfc_is_present() of false -> ?CONSOLE( - "~n===============================================~n" - " You need to install abnfc to compile ABNF grammars~n" - " Download the latest tarball release from github~n" - " https://github.com/nygge/abnfc~n" - " and install it into your erlang library dir~n" - "===============================================~n~n", []), + <<"~n===============================================~n" + " You need to install abnfc to compile ABNF grammars~n" + " Download the latest tarball release from github~n" + " https://github.com/nygge/abnfc~n" + " and install it into your erlang library dir~n" + "===============================================~n~n">>, []), ?FAIL; true -> AbnfcOpts = abnfc_opts(Config), @@ -98,7 +98,7 @@ compile_abnfc(Source, _Target, Config) -> Opts = [noobj, {o, option(out_dir, AbnfcOpts)}, {mod, filename:basename(Source, SourceExt) ++ - option(module_ext, AbnfcOpts)}], + option(module_ext, AbnfcOpts)}], case abnfc:file(Source, Opts) of ok -> ok; Error -> diff --git a/src/rebar_base_compiler.erl b/src/rebar_base_compiler.erl index 341957c..10a495d 100644 --- a/src/rebar_base_compiler.erl +++ b/src/rebar_base_compiler.erl @@ -52,7 +52,8 @@ run(Config, FirstFiles, RestFiles, CompileFn) -> compile_queue(Pids, RestFiles) end. -run(Config, FirstFiles, SourceDir, SourceExt, TargetDir, TargetExt, Compile3Fn) -> +run(Config, FirstFiles, SourceDir, SourceExt, TargetDir, TargetExt, + Compile3Fn) -> run(Config, FirstFiles, SourceDir, SourceExt, TargetDir, TargetExt, Compile3Fn, [check_last_mod]). @@ -73,7 +74,8 @@ run(Config, FirstFiles, SourceDir, SourceExt, TargetDir, TargetExt, run(Config, FirstFiles, RestFiles, fun(S, C) -> - Target = target_file(S, SourceDir, SourceExt, TargetDir, TargetExt), + Target = target_file(S, SourceDir, SourceExt, + TargetDir, TargetExt), simple_compile_wrapper(S, Target, Compile3Fn, C, CheckLastMod) end). diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 5a6bebd..db3e0b4 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -50,10 +50,10 @@ skip_dir(Dir) -> is_skip_dir(Dir) -> case erlang:get({skip_dir, Dir}) of - undefined -> - false; - true -> - true + undefined -> + false; + true -> + true end. skip_dirs() -> @@ -76,7 +76,8 @@ process_commands([Command | Rest]) -> lists:foreach(fun (D) -> erlang:erase({skip_dir, D}) end, skip_dirs()), Operations = erlang:get(operations), - _ = process_dir(rebar_utils:get_cwd(), rebar_config:new(), Command, sets:new()), + _ = process_dir(rebar_utils:get_cwd(), rebar_config:new(), + Command, sets:new()), case erlang:get(operations) of Operations -> %% This command didn't do anything @@ -108,7 +109,8 @@ process_dir(Dir, ParentConfig, Command, DirSet) -> %% CWD to see if it's a fit -- if it is, use that set of modules %% to process this dir. {ok, AvailModuleSets} = application:get_env(rebar, modules), - {DirModules, ModuleSetFile} = choose_module_set(AvailModuleSets, Dir), + {DirModules, ModuleSetFile} = choose_module_set(AvailModuleSets, + Dir), %% Get the list of modules for "any dir". This is a catch-all list %% of modules that are processed in addition to modules associated @@ -122,7 +124,8 @@ process_dir(Dir, ParentConfig, Command, DirSet) -> %% directories that should be processed _before_ the current one. Predirs = acc_modules(Modules, preprocess, Config, ModuleSetFile), ?DEBUG("Predirs: ~p\n", [Predirs]), - DirSet2 = process_each(Predirs, Command, Config, ModuleSetFile, DirSet), + DirSet2 = process_each(Predirs, Command, Config, + ModuleSetFile, DirSet), %% Make sure the CWD is reset properly; processing the dirs may have %% caused it to change @@ -131,27 +134,30 @@ process_dir(Dir, ParentConfig, Command, DirSet) -> %% Check that this directory is not on the skip list case is_skip_dir(Dir) of true -> - %% Do not execute the command on the directory, as some module - %% as requested a skip on it. + %% Do not execute the command on the directory, as some + %% module as requested a skip on it. ?INFO("Skipping ~s in ~s\n", [Command, Dir]); false -> - %% Get the list of plug-in modules from rebar.config. These modules are - %% processed LAST and do not participate in preprocess. + %% Get the list of plug-in modules from rebar.config. These + %% modules are processed LAST and do not participate + %% in preprocess. {ok, PluginModules} = plugin_modules(Config), %% Execute the current command on this directory - execute(Command, Modules ++ PluginModules, Config, ModuleSetFile) + execute(Command, Modules ++ PluginModules, + Config, ModuleSetFile) end, %% Mark the current directory as processed DirSet3 = sets:add_element(Dir, DirSet2), - %% Invoke 'postprocess' on the modules -- this yields a list of other + %% Invoke 'postprocess' on the modules. This yields a list of other %% directories that should be processed _after_ the current one. Postdirs = acc_modules(Modules, postprocess, Config, ModuleSetFile), ?DEBUG("Postdirs: ~p\n", [Postdirs]), - DirSet4 = process_each(Postdirs, Command, Config, ModuleSetFile, DirSet3), + DirSet4 = process_each(Postdirs, Command, Config, + ModuleSetFile, DirSet3), %% Make sure the CWD is reset properly; processing the dirs may have %% caused it to change @@ -220,11 +226,13 @@ execute(Command, Modules, Config, ModuleFile) -> Dir = rebar_utils:get_cwd(), ?CONSOLE("==> ~s (~s)\n", [filename:basename(Dir), Command]), - %% Increment the count of operations, since some module responds to this command + %% Increment the count of operations, since some module + %% responds to this command erlang:put(operations, erlang:get(operations) + 1), %% Run the available modules - case catch(run_modules(TargetModules, Command, Config, ModuleFile)) of + case catch(run_modules(TargetModules, Command, + Config, ModuleFile)) of ok -> ok; {error, failed} -> diff --git a/src/rebar_ct.erl b/src/rebar_ct.erl index a7fc889..8f7c71a 100644 --- a/src/rebar_ct.erl +++ b/src/rebar_ct.erl @@ -165,21 +165,22 @@ get_cover_config(Config, Cwd) -> false -> ""; true -> - case filelib:fold_files(Cwd, ".*cover\.spec\$", true, fun collect_ct_specs/2, []) of - [] -> - ?DEBUG("No cover spec found: ~s~n", [Cwd]), - ""; - [Spec] -> - ?DEBUG("Found cover file ~w~n", [Spec]), - " -cover " ++ Spec; - Specs -> - ?ABORT("Multiple cover specs found: ~p~n", [Specs]) - end - end. + case filelib:fold_files(Cwd, ".*cover\.spec\$", + true, fun collect_ct_specs/2, []) of + [] -> + ?DEBUG("No cover spec found: ~s~n", [Cwd]), + ""; + [Spec] -> + ?DEBUG("Found cover file ~w~n", [Spec]), + " -cover " ++ Spec; + Specs -> + ?ABORT("Multiple cover specs found: ~p~n", [Specs]) + end + end. collect_ct_specs(F, Acc) -> - %% Ignore any specs under the deps/ directory. Do this pulling the dirname off the - %% the F and then splitting it into a list. + %% Ignore any specs under the deps/ directory. Do this pulling + %% the dirname off the the F and then splitting it into a list. Parts = filename:split(filename:dirname(F)), case lists:member("deps", Parts) of true -> diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl index 8f31d0f..99ede3d 100644 --- a/src/rebar_deps.erl +++ b/src/rebar_deps.erl @@ -47,9 +47,9 @@ %% =================================================================== preprocess(Config, _) -> - %% Side effect to set deps_dir globally for all dependencies from top level down. - %% Means the root deps_dir is honoured or the default used globally - %% since it will be set on the first time through here + %% Side effect to set deps_dir globally for all dependencies from + %% top level down. Means the root deps_dir is honoured or the default + %% used globally since it will be set on the first time through here set_global_deps_dir(Config, rebar_config:get_global(deps_dir, [])), %% Get the list of deps for the current working directory and identify those @@ -69,8 +69,8 @@ preprocess(Config, _) -> case rebar_config:get_global(skip_deps, false) of "true" -> lists:foreach(fun (#dep{dir = Dir}) -> - rebar_core:skip_dir(Dir) - end, AvailableDeps); + rebar_core:skip_dir(Dir) + end, AvailableDeps); _ -> ok end, @@ -100,9 +100,9 @@ compile(Config, AppFile) -> ok; {_, MissingDeps} -> lists:foreach(fun (#dep{app=App, vsn_regex=Vsn, source=Src}) -> - ?CONSOLE("Dependency not available: ~p-~s (~p)\n", - [App, Vsn, Src]) - end, MissingDeps), + ?CONSOLE("Dependency not available: " + "~p-~s (~p)\n", [App, Vsn, Src]) + end, MissingDeps), ?FAIL end. @@ -148,7 +148,8 @@ compile(Config, AppFile) -> %% need all deps in same dir and should be the one set by the root rebar.config %% Sets a default if root config has no deps_dir set set_global_deps_dir(Config, []) -> - rebar_config:set_global(deps_dir, rebar_config:get_local(Config, deps_dir, "deps")); + rebar_config:set_global(deps_dir, + rebar_config:get_local(Config, deps_dir, "deps")); set_global_deps_dir(_Config, _DepsDir) -> ok. @@ -253,13 +254,14 @@ is_app_available(App, VsnRegex, Path) -> {expected, VsnRegex}, {has, Vsn}}}} end; OtherApp -> - ?WARN("~s has application id ~p; expected ~p\n", [AppFile, OtherApp, App]), + ?WARN("~s has application id ~p; expected ~p\n", + [AppFile, OtherApp, App]), {false, {name_mismatch, {AppFile, {expected, App}, {has, OtherApp}}}} end; false -> - ?WARN("Expected ~s to be an app dir (containing ebin/*.app), but no .app found.\n", - [Path]), + ?WARN("Expected ~s to be an app dir (containing ebin/*.app), " + "but no .app found.\n", [Path]), {false, {missing_app_file, Path}} end. @@ -267,12 +269,14 @@ use_source(Dep) -> use_source(Dep, 3). use_source(Dep, 0) -> - ?ABORT("Failed to acquire source from ~p after 3 tries.\n", [Dep#dep.source]); + ?ABORT("Failed to acquire source from ~p after 3 tries.\n", + [Dep#dep.source]); use_source(Dep, Count) -> case filelib:is_dir(Dep#dep.dir) of true -> - %% Already downloaded -- verify the versioning matches up with our regex - case is_app_available(Dep#dep.app, Dep#dep.vsn_regex, Dep#dep.dir) of + %% Already downloaded -- verify the versioning matches the regex + case is_app_available(Dep#dep.app, + Dep#dep.vsn_regex, Dep#dep.dir) of {true, _} -> Dir = filename:join(Dep#dep.dir, "ebin"), ok = filelib:ensure_dir(filename:join(Dir, "dummy")), @@ -284,7 +288,7 @@ use_source(Dep, Count) -> %% The app that was downloaded doesn't match up (or had %% errors or something). For the time being, abort. ?ABORT("Dependency dir ~s failed application validation " - "with reason:~n~p.\n", [Dep#dep.dir, Reason]) + "with reason:~n~p.\n", [Dep#dep.dir, Reason]) end; false -> ?CONSOLE("Pulling ~p from ~p\n", [Dep#dep.app, Dep#dep.source]), @@ -335,7 +339,8 @@ update_source(Dep) -> update_source(AppDir, Dep#dep.source), Dep; false -> - ?WARN("Skipping update for ~p: no VCS directory available!\n", [Dep]), + ?WARN("Skipping update for ~p: " + "no VCS directory available!\n", [Dep]), Dep end. @@ -390,13 +395,17 @@ required_scm_client_vsn(bzr) -> {2, 0}; required_scm_client_vsn(svn) -> {1, 6}. scm_client_vsn(hg) -> - scm_client_vsn(rebar_utils:find_executable("hg"), " --version", "version (\\d+).(\\d+)"); + scm_client_vsn(rebar_utils:find_executable("hg"), " --version", + "version (\\d+).(\\d+)"); scm_client_vsn(git) -> - scm_client_vsn(rebar_utils:find_executable("git"), " --version", "git version (\\d+).(\\d+)"); + scm_client_vsn(rebar_utils:find_executable("git"), " --version", + "git version (\\d+).(\\d+)"); scm_client_vsn(bzr) -> - scm_client_vsn(rebar_utils:find_executable("bzr"), " --version", "Bazaar \\(bzr\\) (\\d+).(\\d+)"); + scm_client_vsn(rebar_utils:find_executable("bzr"), " --version", + "Bazaar \\(bzr\\) (\\d+).(\\d+)"); scm_client_vsn(svn) -> - scm_client_vsn(rebar_utils:find_executable("svn"), " --version", "svn, version (\\d+).(\\d+)"). + scm_client_vsn(rebar_utils:find_executable("svn"), " --version", + "svn, version (\\d+).(\\d+)"). has_vcs_dir(git, Dir) -> filelib:is_dir(filename:join(Dir, ".git")); diff --git a/src/rebar_dialyzer.erl b/src/rebar_dialyzer.erl index ea2bd49..c3e3c36 100644 --- a/src/rebar_dialyzer.erl +++ b/src/rebar_dialyzer.erl @@ -31,15 +31,19 @@ %%
  • build-plt (essentially "dialyzer --build_plt -r <app_dirs>")
  • %%
  • check-plt (essentially "dialyzer --check_plt")
  • %% -%% A single option plt can be presented in the dialyzer_opts -%% options in rebar.config. If it is present, it is used as the PLT for the -%% supported commands. Should it not be present, then the default is $HOME/.dialyzer_plt. -%% @reference Experience from developing the Dialyzer: -%% A static analysis tool detecting defects in Erlang applications -%% @reference A Language for Specifying Type -%% Contracts in Erlang and its Interaction with Success Typings -%% @reference Gradual Typing of Erlang -%% Programs: A Wrangler Experience +%% A single option plt can be presented in the +%% dialyzer_opts options in rebar.config. If it +%% is present, it is used as the PLT for the supported commands. Should it +%% not be present, then the default is $HOME/.dialyzer_plt. +%% +%% @reference +%% Experience from developing the Dialyzer: A static analysis tool detecting +%% defects in Erlang applications +%% @reference +%% A Language for Specifying Type Contracts in Erlang and its Interaction +%% with Success Typings +%% @reference Gradual +%% Typing of Erlang Programs: A Wrangler Experience %% @copyright 2010 Dave Smith %% ------------------------------------------------------------------- -module(rebar_dialyzer). @@ -67,12 +71,12 @@ dialyze(Config, File) -> dialyzer_opts, [])), DialyzerOpts0 = case FromSrc of - true -> - [{files_rec, ["src"]}, {init_plt, Plt}, - {from, src_code}]; - false -> - [{files_rec, ["ebin"]}, {init_plt, Plt}] - end, + true -> + [{files_rec, ["src"]}, {init_plt, Plt}, + {from, src_code}]; + false -> + [{files_rec, ["ebin"]}, {init_plt, Plt}] + end, WarnOpts = warnings(Config), DialyzerOpts = case WarnOpts of [] -> DialyzerOpts0; @@ -150,7 +154,7 @@ app_dirs(Apps) -> -spec output_warnings(Warnings::[warning()]) -> 'ok'. output_warnings(Warnings) -> lists:foreach(fun(Warning) -> - ?CONSOLE("~s", [dialyzer:format_warning(Warning)]) + ?CONSOLE("~s", [dialyzer:format_warning(Warning)]) end, Warnings). %% @doc If the plt option is present in rebar.config return its value, otherwise diff --git a/src/rebar_edoc.erl b/src/rebar_edoc.erl index 8a0b7a5..8eda04d 100644 --- a/src/rebar_edoc.erl +++ b/src/rebar_edoc.erl @@ -27,10 +27,12 @@ %% @author Dave Smith %% @doc rebar_edoc supports the following command: %%
      -%%
    • doc (essentially erl -noshell -run edoc_run application "'$(<app_name>)'" +%%
    • doc (essentially erl -noshell -run edoc_run application +%% "'$(<app_name>)'" %% '"."' '[<options>]')
    • %%
    -%% EDoc options can be given in the edoc_opts option in rebar.config. +%% EDoc options can be given in the edoc_opts option in +%% rebar.config. %% @copyright 2010 Dave Smith %% ------------------------------------------------------------------- -module(rebar_edoc). diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 14dd4df..7f02e89 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -70,19 +70,19 @@ -spec compile(Config::#config{}, AppFile::string()) -> 'ok'. compile(Config, _AppFile) -> rebar_base_compiler:run(Config, - check_files(rebar_config:get_local(Config, - xrl_first_files, [])), + check_files(rebar_config:get_local( + Config, xrl_first_files, [])), "src", ".xrl", "src", ".erl", fun compile_xrl/3), rebar_base_compiler:run(Config, - check_files(rebar_config:get_local(Config, - yrl_first_files, [])), + check_files(rebar_config:get_local( + 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, [])), + check_files(rebar_config:get_local( + Config, mib_first_files, [])), "mibs", ".mib", "priv/mibs", ".bin", fun compile_mib/3). @@ -132,19 +132,20 @@ doterl_compile(Config, OutDir, MoreSources) -> RestErls = [Source || Source <- gather_src(SrcDirs, []) ++ MoreSources, not lists:member(Source, FirstErls)], - % Split RestErls so that parse_transforms and behaviours are instead added - % to erl_first_files, parse transforms first. - % This should probably be somewhat combined with inspect_epp - [ParseTransforms, Behaviours, OtherErls] = lists:foldl(fun(F, [A, B, C]) -> - case compile_priority(F) of - parse_transform -> - [[F | A], B, C]; - behaviour -> - [A, [F | B], C]; - _ -> - [A, B, [F | C]] - end - end, [[], [], []], RestErls), + %% Split RestErls so that parse_transforms and behaviours are instead added + %% to erl_first_files, parse transforms first. + %% This should probably be somewhat combined with inspect_epp + [ParseTransforms, Behaviours, OtherErls] = + lists:foldl(fun(F, [A, B, C]) -> + case compile_priority(F) of + parse_transform -> + [[F | A], B, C]; + behaviour -> + [A, [F | B], C]; + _ -> + [A, B, [F | C]] + end + end, [[], [], []], RestErls), NewFirstErls = FirstErls ++ ParseTransforms ++ Behaviours, @@ -167,9 +168,11 @@ doterl_compile(Config, OutDir, MoreSources) -> -spec include_path(Source::string(), Config::#config{}) -> [string(), ...]. include_path(Source, Config) -> ErlOpts = rebar_config:get(Config, erl_opts, []), - ["include", filename:dirname(Source)] ++ proplists:get_all_values(i, ErlOpts). + ["include", filename:dirname(Source)] + ++ proplists:get_all_values(i, ErlOpts). --spec inspect(Source::string(), IncludePath::[string(),...]) -> {string(), [string()]}. +-spec inspect(Source::string(), + IncludePath::[string(),...]) -> {string(), [string()]}. inspect(Source, IncludePath) -> ModuleDefault = filename:basename(Source, ".erl"), case epp:open(Source, IncludePath) of @@ -180,7 +183,8 @@ inspect(Source, IncludePath) -> {ModuleDefault, []} end. --spec inspect_epp(Epp::pid(), Source::string(), Module::string(), Includes::[string()]) -> {string(), [string()]}. +-spec inspect_epp(Epp::pid(), Source::string(), Module::string(), + Includes::[string()]) -> {string(), [string()]}. inspect_epp(Epp, Source, Module, Includes) -> case epp:parse_erl_form(Epp) of {ok, {attribute, _, module, ModInfo}} -> @@ -190,13 +194,15 @@ inspect_epp(Epp, Source, Module, Includes) -> ActualModuleStr = atom_to_list(ActualModule); %% Packag-ized module name, list of atoms ActualModule when is_list(ActualModule) -> - ActualModuleStr = string:join([atom_to_list(P) || P <- ActualModule], "."); + ActualModuleStr = string:join([atom_to_list(P) || + P <- ActualModule], "."); %% Parameterized module name, single atom {ActualModule, _} when is_atom(ActualModule) -> ActualModuleStr = atom_to_list(ActualModule); %% Parameterized and packagized module name, list of atoms {ActualModule, _} when is_list(ActualModule) -> - ActualModuleStr = string:join([atom_to_list(P) || P <- ActualModule], ".") + ActualModuleStr = string:join([atom_to_list(P) || + P <- ActualModule], ".") end, inspect_epp(Epp, Source, ActualModuleStr, Includes); {ok, {attribute, 1, file, {Module, 1}}} -> @@ -212,14 +218,16 @@ inspect_epp(Epp, Source, Module, Includes) -> inspect_epp(Epp, Source, Module, Includes) end. --spec needs_compile(Source::string(), Target::string(), Hrls::[string()]) -> boolean(). +-spec needs_compile(Source::string(), Target::string(), + Hrls::[string()]) -> boolean(). needs_compile(Source, Target, Hrls) -> TargetLastMod = filelib:last_modified(Target), lists:any(fun(I) -> TargetLastMod < filelib:last_modified(I) end, [Source] ++ Hrls). -spec internal_erl_compile(Source::string(), Config::#config{}, - Outdir::string(), ErlOpts::list()) -> 'ok' | 'skipped'. + Outdir::string(), + ErlOpts::list()) -> 'ok' | 'skipped'. internal_erl_compile(Source, Config, Outdir, ErlOpts) -> %% Determine the target name and includes list by inspecting the source file {Module, Hrls} = inspect(Source, include_path(Source, Config)), @@ -238,7 +246,8 @@ internal_erl_compile(Source, Config, Outdir, ErlOpts) -> {ok, _, []} -> ok; {ok, _, _Warnings} -> - %% We got at least one warning -- if fail_on_warning is in options, fail + %% We got at least one warning -- if fail_on_warning + %% is in options, fail case lists:member(fail_on_warning, Opts) of true -> %% remove target to prevent overlooking this failure @@ -254,7 +263,8 @@ internal_erl_compile(Source, Config, Outdir, ErlOpts) -> skipped end. --spec compile_mib(Source::string(), Target::string(), Config::#config{}) -> 'ok'. +-spec compile_mib(Source::string(), Target::string(), + Config::#config{}) -> 'ok'. compile_mib(Source, Target, Config) -> ok = rebar_utils:ensure_dir(Target), Opts = [{outdir, "priv/mibs"}, {i, ["priv/mibs"]}] ++ @@ -266,13 +276,15 @@ compile_mib(Source, Target, Config) -> ?FAIL end. --spec compile_xrl(Source::string(), Target::string(), Config::#config{}) -> 'ok'. +-spec compile_xrl(Source::string(), Target::string(), + Config::#config{}) -> 'ok'. compile_xrl(Source, Target, Config) -> Opts = [{scannerfile, Target}, {return, true} |rebar_config:get(Config, xrl_opts, [])], compile_xrl_yrl(Source, Target, Opts, leex). --spec compile_yrl(Source::string(), Target::string(), Config::#config{}) -> 'ok'. +-spec compile_yrl(Source::string(), Target::string(), + Config::#config{}) -> 'ok'. compile_yrl(Source, Target, Config) -> Opts = [{parserfile, Target}, {return, true} |rebar_config:get(Config, yrl_opts, [])], @@ -315,7 +327,8 @@ src_dirs(SrcDirs) -> dirs(Dir) -> [F || F <- filelib:wildcard(filename:join([Dir, "*"])), filelib:is_dir(F)]. --spec delete_dir(Dir::string(), Subdirs::[string()]) -> 'ok' | {'error', atom()}. +-spec delete_dir(Dir::string(), + Subdirs::[string()]) -> 'ok' | {'error', atom()}. delete_dir(Dir, []) -> file:del_dir(Dir); delete_dir(Dir, Subdirs) -> @@ -330,23 +343,24 @@ compile_priority(File) -> normal; % couldn't parse the file, default priority {ok, Trees} -> F2 = fun({tree,arity_qualifier,_, - {arity_qualifier,{tree,atom,_,behaviour_info}, - {tree,integer,_,1}}}, _) -> - behaviour; - ({tree,arity_qualifier,_, - {arity_qualifier,{tree,atom,_,parse_transform}, - {tree,integer,_,2}}}, _) -> - parse_transform; - (_, Acc) -> - Acc - end, - - F = fun({tree, attribute, _, {attribute, {tree, atom, _, export}, - [{tree, list, _, {list, List, none}}]}}, Acc) -> - lists:foldl(F2, Acc, List); - (_, Acc) -> - Acc - end, + {arity_qualifier,{tree,atom,_,behaviour_info}, + {tree,integer,_,1}}}, _) -> + behaviour; + ({tree,arity_qualifier,_, + {arity_qualifier,{tree,atom,_,parse_transform}, + {tree,integer,_,2}}}, _) -> + parse_transform; + (_, Acc) -> + Acc + end, + + F = fun({tree, attribute, _, + {attribute, {tree, atom, _, export}, + [{tree, list, _, {list, List, none}}]}}, Acc) -> + lists:foldl(F2, Acc, List); + (_, Acc) -> + Acc + end, lists:foldl(F, normal, Trees) end. diff --git a/src/rebar_erlydtl_compiler.erl b/src/rebar_erlydtl_compiler.erl index 654fd74..f17e8fd 100644 --- a/src/rebar_erlydtl_compiler.erl +++ b/src/rebar_erlydtl_compiler.erl @@ -83,8 +83,10 @@ compile(Config, _AppFile) -> DtlOpts = erlydtl_opts(Config), rebar_base_compiler:run(Config, [], - option(doc_root, DtlOpts), option(source_ext, DtlOpts), - option(out_dir, DtlOpts), option(module_ext, DtlOpts) ++ ".beam", + option(doc_root, DtlOpts), + option(source_ext, DtlOpts), + option(out_dir, DtlOpts), + option(module_ext, DtlOpts) ++ ".beam", fun compile_dtl/3, [{check_last_mod, false}]). @@ -102,18 +104,18 @@ default(doc_root) -> "templates"; default(out_dir) -> "ebin"; default(source_ext) -> ".dtl"; default(module_ext) -> "_dtl"; -default(custom_tags_dir) -> "". +default(custom_tags_dir) -> "". compile_dtl(Source, Target, Config) -> case code:which(erlydtl) of non_existing -> ?CONSOLE( - "~n===============================================~n" - " You need to install erlydtl to compile DTL templates~n" - " Download the latest tarball release from github~n" - " http://code.google.com/p/erlydtl/~n" - " and install it into your erlang library dir~n" - "===============================================~n~n", []), + <<"~n===============================================~n" + " You need to install erlydtl to compile DTL templates~n" + " Download the latest tarball release from github~n" + " http://code.google.com/p/erlydtl/~n" + " and install it into your erlang library dir~n" + "===============================================~n~n">>, []), ?FAIL; _ -> case needs_compile(Source, Target, Config) of diff --git a/src/rebar_escripter.erl b/src/rebar_escripter.erl index 5ee95e9..8b23263 100644 --- a/src/rebar_escripter.erl +++ b/src/rebar_escripter.erl @@ -48,7 +48,8 @@ escriptize(Config, AppFile) -> %% Look for a list of other applications (dependencies) to include %% in the output file. We then use the .app files for each of these %% to pull in all the .beam files. - InclBeams = get_app_beams(rebar_config:get_local(Config, escript_incl_apps, []), []), + InclBeams = get_app_beams( + rebar_config:get_local(Config, escript_incl_apps, []), []), %% Construct the archive of everything in ebin/ dir -- put it on the %% top-level of the zip file so that code loading works properly. @@ -62,11 +63,13 @@ escriptize(Config, AppFile) -> ok -> ok; {error, WriteError} -> - ?ERROR("Failed to write ~p script: ~p\n", [AppName, WriteError]), + ?ERROR("Failed to write ~p script: ~p\n", + [AppName, WriteError]), ?FAIL end; {error, ZipError} -> - ?ERROR("Failed to construct ~p escript: ~p\n", [AppName, ZipError]), + ?ERROR("Failed to construct ~p escript: ~p\n", + [AppName, ZipError]), ?FAIL end, @@ -94,9 +97,11 @@ get_app_beams([], Acc) -> get_app_beams([App | Rest], Acc) -> case code:lib_dir(App, ebin) of {error, bad_name} -> - ?ABORT("Failed to get ebin/ directory for ~p escript_incl_apps.", [App]); + ?ABORT("Failed to get ebin/ directory for " + "~p escript_incl_apps.", [App]); Path -> - Acc2 = [{filename:join([App, ebin, F]), file_contents(filename:join(Path, F))} || + Acc2 = [{filename:join([App, ebin, F]), + file_contents(filename:join(Path, F))} || F <- filelib:wildcard("*", Path)], get_app_beams(Rest, Acc2 ++ Acc) end. diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl index a05afd3..01fb805 100644 --- a/src/rebar_eunit.erl +++ b/src/rebar_eunit.erl @@ -36,8 +36,9 @@ %%
  • suite="foo"" - runs test/foo_tests.erl
  • %% %% Additionally, for projects that have separate folders for the core -%% implementation, and for the unit tests, then the following rebar.config -%% option can be provided: {eunit_compile_opts, [{src_dirs, ["dir"]}]}.. +%% implementation, and for the unit tests, then the following +%% rebar.config option can be provided: +%% {eunit_compile_opts, [{src_dirs, ["dir"]}]}.. %% @copyright 2009, 2010 Dave Smith %% ------------------------------------------------------------------- -module(rebar_eunit). @@ -78,16 +79,17 @@ eunit(Config, AppFile) -> ok = filelib:ensure_dir(eunit_dir() ++ "/foo"), ok = filelib:ensure_dir(ebin_dir() ++ "/foo"), - %% Setup code path prior to compilation so that parse_transforms and the like - %% work properly. Also, be sure to add ebin_dir() to the END of the code path - %% so that we don't have to jump through hoops to access the .app file + %% Setup code path prior to compilation so that parse_transforms + %% and the like work properly. Also, be sure to add ebin_dir() + %% to the END of the code path so that we don't have to jump + %% through hoops to access the .app file CodePath = code:get_path(), true = code:add_patha(eunit_dir()), true = code:add_pathz(ebin_dir()), %% Obtain all the test modules for inclusion in the compile stage. - %% Notice: this could also be achieved with the following rebar.config option: - %% {eunit_compile_opts, [{src_dirs, ["test"]}]} + %% Notice: this could also be achieved with the following + %% rebar.config option: {eunit_compile_opts, [{src_dirs, ["test"]}]} TestErls = rebar_utils:find_files("test", ".*\\.erl\$"), %% Copy source files to eunit dir for cover in case they are not directly @@ -99,7 +101,8 @@ eunit(Config, AppFile) -> %% Compile erlang code to ?EUNIT_DIR, using a tweaked config %% with appropriate defines for eunit, and include all the test modules %% as well. - rebar_erlc_compiler:doterl_compile(eunit_config(Config), ?EUNIT_DIR, TestErls), + rebar_erlc_compiler:doterl_compile(eunit_config(Config), + ?EUNIT_DIR, TestErls), %% Build a list of all the .beams in ?EUNIT_DIR -- use this for cover %% and eunit testing. Normally you can just tell cover and/or eunit to @@ -111,7 +114,7 @@ eunit(Config, AppFile) -> string:str(N, "_tests.beam") =:= 0], Modules = [rebar_utils:beam_to_mod(?EUNIT_DIR, N) || N <- BeamFiles], SrcModules = [rebar_utils:erl_to_mod(M) || M <- SrcErls], - + cover_init(Config, BeamFiles), EunitResult = perform_eunit(Config, Modules), perform_cover(Config, Modules, SrcModules), @@ -205,7 +208,7 @@ is_quickcheck_avail() -> end. perform_cover(Config, BeamFiles, SrcModules) -> - perform_cover(rebar_config:get(Config, cover_enabled, false), + perform_cover(rebar_config:get(Config, cover_enabled, false), Config, BeamFiles, SrcModules). perform_cover(false, _Config, _BeamFiles, _SrcModules) -> @@ -227,7 +230,8 @@ cover_analyze(Config, Modules, SrcModules) -> %% Write coverage details for each file lists:foreach(fun({M, _, _}) -> - {ok, _} = cover:analyze_to_file(M, cover_file(M), [html]) + {ok, _} = cover:analyze_to_file(M, cover_file(M), + [html]) end, Coverage), Index = filename:join([rebar_utils:get_cwd(), ?EUNIT_DIR, "index.html"]), @@ -260,7 +264,12 @@ cover_init(true, BeamFiles) -> %% It's not an error for cover compilation to fail partially, %% but we do want to warn about them - _ = [?CONSOLE("Cover compilation warning for ~p: ~p", [Beam, Desc]) || {Beam, {error, Desc}} <- Compiled], + PrintWarning = + fun(Beam, Desc) -> + ?CONSOLE("Cover compilation warning for ~p: ~p", + [Beam, Desc]) + end, + _ = [PrintWarning(Beam, Desc) || {Beam, {error, Desc}} <- Compiled], ok end; cover_init(Config, BeamFiles) -> @@ -287,18 +296,19 @@ is_eunitized(Mod) -> has_eunit_test_fun(Mod) -> [F || {exports, Funs} <- Mod:module_info(), - {F, 0} <- Funs, F =:= test] =/= []. + {F, 0} <- Funs, F =:= test] =/= []. has_header(Mod, Header) -> - Mod1 = case code:which(Mod) of - cover_compiled -> + Mod1 = case code:which(Mod) of + cover_compiled -> {file, File} = cover:is_compiled(Mod), File; non_existing -> Mod; preloaded -> Mod; L -> L end, - {ok, {_, [{abstract_code, {_, AC}}]}} = beam_lib:chunks(Mod1, [abstract_code]), + {ok, {_, [{abstract_code, {_, AC}}]}} = beam_lib:chunks(Mod1, + [abstract_code]), [F || {attribute, 1, file, {F, 1}} <- AC, string:str(F, Header) =/= 0] =/= []. @@ -310,7 +320,7 @@ align_notcovered_count(Module, Covered, NotCovered, true) -> cover_write_index(Coverage, SrcModules) -> {ok, F} = file:open(filename:join([?EUNIT_DIR, "index.html"]), [write]), ok = file:write(F, "Coverage Summary\n"), - IsSrcCoverage = fun({Mod,_C,_N}) -> lists:member(Mod, SrcModules) end, + IsSrcCoverage = fun({Mod,_C,_N}) -> lists:member(Mod, SrcModules) end, {SrcCoverage, TestCoverage} = lists:partition(IsSrcCoverage, Coverage), cover_write_index_section(F, "Source", SrcCoverage), cover_write_index_section(F, "Test", TestCoverage), @@ -331,9 +341,13 @@ cover_write_index_section(F, SectionName, Coverage) -> ok = file:write(F, ?FMT("

    Total: ~s

    \n", [TotalCoverage])), ok = file:write(F, "\n"), + FmtLink = + fun(Module, Cov, NotCov) -> + ?FMT("\n", + [Module, Module, percentage(Cov, NotCov)]) + end, lists:foreach(fun({Module, Cov, NotCov}) -> - ok = file:write(F, ?FMT("\n", - [Module, Module, percentage(Cov, NotCov)])) + ok = file:write(F, FmtLink(Module, Cov, NotCov)) end, Coverage), ok = file:write(F, "
    ModuleCoverage %
    ~s~s
    ~s~s
    \n"). @@ -345,13 +359,13 @@ cover_print_coverage(Coverage) -> %% Determine the longest module name for right-padding Width = lists:foldl(fun({Mod, _, _}, Acc) -> - case length(atom_to_list(Mod)) of - N when N > Acc -> - N; - _ -> - Acc - end - end, 0, Coverage) * -1, + case length(atom_to_list(Mod)) of + N when N > Acc -> + N; + _ -> + Acc + end + end, 0, Coverage) * -1, %% Print the output the console ?CONSOLE("~nCode Coverage:~n", []), diff --git a/src/rebar_file_utils.erl b/src/rebar_file_utils.erl index 1e8e523..731f9d9 100644 --- a/src/rebar_file_utils.erl +++ b/src/rebar_file_utils.erl @@ -132,7 +132,7 @@ xcopy_win32(Source,Dest)-> end. cp_r_win32({true, SourceDir}, {true, DestDir}) -> - % from directory to directory + %% from directory to directory SourceBase = filename:basename(SourceDir), ok = case file:make_dir(filename:join(DestDir, SourceBase)) of {error, eexist} -> ok; @@ -140,10 +140,10 @@ cp_r_win32({true, SourceDir}, {true, DestDir}) -> end, ok = xcopy_win32(SourceDir, filename:join(DestDir, SourceBase)); cp_r_win32({false, Source} = S,{true, DestDir}) -> - % from file to directory + %% from file to directory cp_r_win32(S, {false, filename:join(DestDir, filename:basename(Source))}); cp_r_win32({false, Source},{false, Dest}) -> - % from file to file + %% from file to file {ok,_} = file:copy(Source, Dest), ok; cp_r_win32(Source,Dest) -> diff --git a/src/rebar_lfe_compiler.erl b/src/rebar_lfe_compiler.erl index d5b6e76..b100e3d 100644 --- a/src/rebar_lfe_compiler.erl +++ b/src/rebar_lfe_compiler.erl @@ -49,12 +49,13 @@ compile(Config, _AppFile) -> compile_lfe(Source, _Target, Config) -> case code:which(lfe_comp) of non_existing -> - ?CONSOLE("~n===============================================~n" ++ - " You need to install LFE to compile LFE source~n" ++ - "Download the latest tarball release from github~n" ++ - " http://github.com/rvirding/lfe/downloads~n" ++ - " and install it into your erlang library dir~n" ++ - "===============================================~n~n", []), + ?CONSOLE( + <<"~n===============================================~n" + " You need to install LFE to compile LFE source files~n" + "Download the latest tarball release from github~n" + " https://github.com/rvirding/lfe/downloads~n" + " and install it into your erlang library dir~n" + "===============================================~n~n">>, []), ?FAIL; _ -> Opts = [{i, "include"}, {outdir, "ebin"}, report, return] ++ diff --git a/src/rebar_log.erl b/src/rebar_log.erl index 3dde0b5..54774d7 100644 --- a/src/rebar_log.erl +++ b/src/rebar_log.erl @@ -81,6 +81,3 @@ log_prefix(debug) -> "DEBUG: "; log_prefix(info) -> "INFO: "; log_prefix(warn) -> "WARN: "; log_prefix(error) -> "ERROR: ". - - - diff --git a/src/rebar_neotoma_compiler.erl b/src/rebar_neotoma_compiler.erl index 4301323..e84ab2a 100644 --- a/src/rebar_neotoma_compiler.erl +++ b/src/rebar_neotoma_compiler.erl @@ -27,7 +27,7 @@ %% The rebar_neotoma module is a plugin for rebar that compiles %% neotoma peg files. By default, it compiles all src/*.peg to src/*.erl -%% +%% %% Configuration options should be placed in rebar.config under %% neotoma_opts. Available options include: %% @@ -52,9 +52,10 @@ compile(Config, _AppFile) -> NeoOpts = neotoma_opts(Config), rebar_base_compiler:run(Config, [], option(doc_root, NeoOpts), ".peg", - option(out_dir, NeoOpts), option(module_ext, NeoOpts) ++ ".beam", + option(out_dir, NeoOpts), + option(module_ext, NeoOpts) ++ ".beam", fun compile_neo/3, [{check_last_mod,false}]). - + %% ============================================================================ %% Public API %% ============================================================================ @@ -71,47 +72,48 @@ default(module_ext) -> ""; default(source_ext) -> ".peg". compile_neo(Source, Target, Config) -> - case code:which(neotoma) of - non_existing -> - ?CONSOLE( - "~n===============================================~n" - " You need to install neotoma to compile PEG grammars~n" - " Download the latest tarball release from github~n" - " http://github.com/seancribbs/neotoma~n" - " and install it into your erlang library dir~n" - "===============================================~n~n", []), - ?FAIL; - _ -> - case needs_compile(Source, Target, Config) of - true -> - do_compile(Source, Target, Config); - false -> - skipped - end - end. - + case code:which(neotoma) of + non_existing -> + ?CONSOLE( + <<"~n===============================================~n" + " You need to install neotoma to compile PEG grammars~n" + " Download the latest tarball release from github~n" + " https://github.com/seancribbs/neotoma~n" + " and install it into your erlang library dir~n" + "===============================================~n~n">>, []), + ?FAIL; + _ -> + case needs_compile(Source, Target, Config) of + true -> + do_compile(Source, Target, Config); + false -> + skipped + end + end. + do_compile(Source, _Target, Config) -> %% TODO: Check last mod on target and referenced DTLs here.. NeoOpts = neotoma_opts(Config), %% ensure that doc_root and out_dir are defined, %% using defaults if necessary Opts = [{output, option(out_dir, NeoOpts)}, - {module, list_to_atom(filename:basename(Source, ".peg") ++ option(module_ext, NeoOpts))}], + {module, list_to_atom(filename:basename(Source, ".peg") + ++ option(module_ext, NeoOpts))}], case neotoma:file(Source, Opts ++ NeoOpts) of - ok -> + ok -> ok; Reason -> ?CONSOLE("Compiling peg ~s failed:~n ~p~n", [Source, Reason]), ?FAIL end. - + needs_compile(Source, Target, Config) -> LM = filelib:last_modified(Target), LM < filelib:last_modified(Source) orelse lists:any(fun(D) -> LM < filelib:last_modified(D) end, referenced_pegs(Source, Config)). - + referenced_pegs(Source, Config) -> Set = referenced_pegs1([Source], Config, sets:add_element(Source, sets:new())), diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl index af579d9..4f21a67 100644 --- a/src/rebar_otp_app.erl +++ b/src/rebar_otp_app.erl @@ -40,11 +40,11 @@ compile(Config, File) -> %% written out as a ebin/*.app file. That resulting file will then %% be validated as usual. AppFile = case rebar_app_utils:is_app_src(File) of - true -> - preprocess(Config, File); - false -> - File - end, + true -> + preprocess(Config, File); + false -> + File + end, %% Load the app file and validate it. case rebar_app_utils:load_app_file(AppFile) of @@ -52,11 +52,12 @@ compile(Config, File) -> validate_name(AppName, AppFile), %% In general, the list of modules is an important thing to validate - %% for compliance with OTP guidelines and upgrade procedures. However, - %% some people prefer not to validate this list. + %% for compliance with OTP guidelines and upgrade procedures. + %% However, some people prefer not to validate this list. case rebar_config:get_local(Config, validate_app_modules, true) of true -> - validate_modules(AppName, proplists:get_value(modules, AppData)); + validate_modules(AppName, + proplists:get_value(modules, AppData)); false -> ok end; @@ -102,13 +103,15 @@ preprocess(Config, AppSrcFile) -> AppFile = rebar_app_utils:app_src_to_app(AppSrcFile), ok = file:write_file(AppFile, Spec), - %% Make certain that the ebin/ directory is available on the code path + %% Make certain that the ebin/ directory is available + %% on the code path true = code:add_path(filename:absname(filename:dirname(AppFile))), AppFile; {error, Reason} -> - ?ABORT("Failed to read ~s for preprocessing: ~p\n", [AppSrcFile, Reason]) + ?ABORT("Failed to read ~s for preprocessing: ~p\n", + [AppSrcFile, Reason]) end. load_app_vars(Config) -> @@ -129,23 +132,25 @@ apply_app_vars([{Key, Value} | Rest], AppData) -> apply_app_vars(Rest, AppData2). validate_name(AppName, File) -> - %% Convert the .app file name to an atom -- check it against the identifier within the file + %% Convert the .app file name to an atom -- check it against the + %% identifier within the file ExpApp = list_to_atom(filename:basename(File, ".app")), case ExpApp == AppName of true -> ok; false -> - ?ERROR("Invalid ~s: name of application (~p) must match filename.\n", - [File, AppName]), + ?ERROR("Invalid ~s: name of application (~p) " + "must match filename.\n", [File, AppName]), ?FAIL end. validate_modules(AppName, undefined) -> - ?ERROR("Missing modules declaration in~p.app:\n", [AppName]), - ?FAIL; + ?ERROR("Missing modules declaration in~p.app:\n", [AppName]), + ?FAIL; validate_modules(AppName, Mods) -> - %% Construct two sets -- one for the actual .beam files in ebin/ and one for the modules + %% Construct two sets -- one for the actual .beam files in ebin/ + %% and one for the modules %% listed in the .app file EbinSet = ordsets:from_list(ebin_modules()), ModSet = ordsets:from_list(Mods), @@ -155,9 +160,10 @@ validate_modules(AppName, Mods) -> [] -> ok; MissingBeams -> - Msg1 = lists:flatten([io_lib:format("\t* ~p\n", [M]) || M <- MissingBeams]), - ?ERROR("One or more modules listed in ~p.app are not present in ebin/*.beam:\n~s", - [AppName, Msg1]), + Msg1 = lists:flatten([io_lib:format("\t* ~p\n", [M]) || + M <- MissingBeams]), + ?ERROR("One or more modules listed in ~p.app are not " + "present in ebin/*.beam:\n~s", [AppName, Msg1]), ?FAIL end, @@ -166,11 +172,13 @@ validate_modules(AppName, Mods) -> [] -> ok; MissingMods -> - Msg2 = lists:flatten([io_lib:format("\t* ~p\n", [M]) || M <- MissingMods]), - ?ERROR("One or more .beam files exist that are not listed in ~p.app:\n~s", - [AppName, Msg2]), + Msg2 = lists:flatten([io_lib:format("\t* ~p\n", [M]) || + M <- MissingMods]), + ?ERROR("One or more .beam files exist that are not " + "listed in ~p.app:\n~s", [AppName, Msg2]), ?FAIL end. ebin_modules() -> - lists:sort([rebar_utils:beam_to_mod("ebin", N) || N <- rebar_utils:beams("ebin")]). + lists:sort([rebar_utils:beam_to_mod("ebin", N) || + N <- rebar_utils:beams("ebin")]). diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl index c8c1cbd..b230af1 100644 --- a/src/rebar_port_compiler.erl +++ b/src/rebar_port_compiler.erl @@ -43,11 +43,14 @@ %% {Regex, String} wherein Regex is a regular expression %% that is checked against the system architecture. %% -%% * so_specs - Erlang list of tuples of the form {"priv/so_name.so", ["c_src/object_file_name.o"]} useful for -%% building multiple *.so files. +%% * so_specs - Erlang list of tuples of the form +%% {"priv/so_name.so", ["c_src/object_file_name.o"]} +%% useful for building multiple *.so files. %% -%% * port_envs - Erlang list of key/value pairs which will control the environment when -%% running the compiler and linker. By default, the following variables +%% * port_envs - Erlang list of key/value pairs which will control +%% the environment when running the compiler and linker. +%% +%% By default, the following variables %% are defined: %% CC - C compiler %% CXX - C++ compiler @@ -59,67 +62,85 @@ %% DRV_CFLAGS - flags that will be used for compiling the driver %% DRV_LDFLAGS - flags that will be used for linking the driver %% -%% Note that if you wish to extend (vs. replace) these variables, you MUST -%% include a shell-style reference in your definition. E.g. to extend CFLAGS, -%% do something like: +%% Note that if you wish to extend (vs. replace) these variables, +%% you MUST include a shell-style reference in your definition. +%% e.g. to extend CFLAGS, do something like: %% %% {port_envs, [{"CFLAGS", "$CFLAGS -MyOtherOptions"}]} %% -%% It is also possible to specify platform specific options by specifying a triplet -%% where the first string is a regex that is checked against erlang's system architecture -%% string. E.g. to specify a CFLAG that only applies to x86_64 on linux do: +%% It is also possible to specify platform specific options +%% by specifying a tripletwhere the first string is a regex +%% that is checked against erlang's system architecture string. +%% e.g. to specify a CFLAG that only applies to x86_64 on linux +%% do: %% -%% {port_envs, [{"x86_64.*-linux", "CFLAGS", "$CFLAGS -X86Options"}]} +%% {port_envs, [{"x86_64.*-linux", "CFLAGS", +%% "$CFLAGS -X86Options"}]} %% -%% * port_pre_script - Tuple which specifies a pre-compilation script to run, and a filename that -%% exists as a result of the script running. +%% * port_pre_script - Tuple which specifies a pre-compilation script to run, +%% and a filename that exists as a result of the script +%% running. %% -%% * port_cleanup_script - String that specifies a script to run during cleanup. Use this to remove -%% files/directories created by port_pre_script. +%% * port_cleanup_script - String that specifies a script to run during cleanup. +%% Use this to remove files/directories created by +%% port_pre_script. %% compile(Config, AppFile) -> %% Compose list of sources from config file -- defaults to c_src/*.c - Sources = expand_sources(rebar_config:get_list(Config, port_sources, ["c_src/*.c"]), []), + Sources = expand_sources(rebar_config:get_list(Config, port_sources, + ["c_src/*.c"]), []), case Sources of [] -> ok; _ -> - %% Extract environment values from the config (if specified) and merge with the - %% default for this operating system. This enables max flexibility for users. + %% Extract environment values from the config (if specified) and + %% merge with the default for this operating system. This enables + %% max flexibility for users. DefaultEnvs = filter_envs(default_env(), []), - OverrideEnvs = filter_envs(rebar_config:get_list(Config, port_envs, []), []), - Env = expand_vars_loop(merge_each_var(DefaultEnvs ++ OverrideEnvs ++ os_env(), [])), + PortEnvs = rebar_config:get_list(Config, port_envs, []), + OverrideEnvs = filter_envs(PortEnvs, []), + RawEnv = DefaultEnvs ++ OverrideEnvs ++ os_env(), + Env = expand_vars_loop(merge_each_var(RawEnv, [])), - %% One or more files are available for building. Run the pre-compile hook, if - %% necessary. + %% One or more files are available for building. + %% Run the pre-compile hook, if necessary. ok = run_precompile_hook(Config, Env), %% Compile each of the sources - {NewBins, ExistingBins} = compile_each(Sources, Config, Env, [], []), + {NewBins, ExistingBins} = compile_each(Sources, Config, Env, + [], []), %% Construct the driver name and make sure priv/ exists SoSpecs = so_specs(Config, AppFile, NewBins ++ ExistingBins), ?INFO("Using specs ~p\n", [SoSpecs]), - lists:foreach(fun({SoName,_}) -> ok = filelib:ensure_dir(SoName) end, SoSpecs), - - %% Only relink if necessary, given the SoName and list of new binaries - lists:foreach(fun({SoName,Bins}) -> - case needs_link(SoName, sets:to_list(sets:intersection([sets:from_list(Bins),sets:from_list(NewBins)]))) of - true -> - rebar_utils:sh(?FMT("$CC ~s $LDFLAGS $DRV_LDFLAGS -o ~s", - [string:join(Bins, " "), SoName]), - [{env, Env}]); - false -> - ?INFO("Skipping relink of ~s\n", [SoName]), - ok - end + lists:foreach(fun({SoName,_}) -> + ok = filelib:ensure_dir(SoName) + end, SoSpecs), + + %% Only relink if necessary, given the SoName + %% and list of new binaries + lists:foreach( + fun({SoName,Bins}) -> + AllBins = [sets:from_list(Bins), sets:from_list(NewBins)], + Intersection = sets:intersection(AllBins), + case needs_link(SoName, sets:to_list(Intersection)) of + true -> + rebar_utils:sh( + ?FMT("$CC ~s $LDFLAGS $DRV_LDFLAGS -o ~s", + [string:join(Bins, " "), SoName]), + [{env, Env}]); + false -> + ?INFO("Skipping relink of ~s\n", [SoName]), + ok + end end, SoSpecs) end. clean(Config, AppFile) -> %% Build a list of sources so as to derive all the bins we generated - Sources = expand_sources(rebar_config:get_list(Config, port_sources, ["c_src/*.c"]), []), + Sources = expand_sources(rebar_config:get_list(Config, port_sources, + ["c_src/*.c"]), []), rebar_file_utils:delete_each([source_to_bin(S) || S <- Sources]), %% Delete the .so file @@ -151,7 +172,7 @@ expand_sources([{ArchRegex, Spec} | Rest], Acc) -> expand_sources([Spec | Rest], Acc) -> Acc2 = filelib:wildcard(Spec) ++ Acc, expand_sources(Rest, Acc2). - + expand_objects(Sources) -> [filename:join([filename:dirname(F), filename:basename(F) ++ ".o"]) || F <- Sources]. @@ -167,7 +188,8 @@ run_precompile_hook(Config, Env) -> {ok, _} = rebar_utils:sh(Script, [{env, Env}]), ok; true -> - ?INFO("~s exists; not running ~s\n", [BypassFileName, Script]) + ?INFO("~s exists; not running ~s\n", + [BypassFileName, Script]) end end. @@ -206,10 +228,9 @@ compile_each([Source | Rest], Config, Env, NewBins, ExistingBins) -> compile_each(Rest, Config, Env, NewBins, [Bin | ExistingBins]) end. - - needs_compile(Source, Bin) -> - %% TODO: Generate depends using gcc -MM so we can also check for include changes + %% TODO: Generate depends using gcc -MM so we can also + %% check for include changes filelib:last_modified(Bin) < filelib:last_modified(Source). needs_link(SoName, []) -> @@ -249,8 +270,8 @@ merge_each_var([], Vars) -> merge_each_var([{Key, Value} | Rest], Vars) -> case orddict:find(Key, Vars) of error -> - %% Nothing yet defined for this key/value. Expand any self-references - %% as blank. + %% Nothing yet defined for this key/value. + %% Expand any self-references as blank. Evalue = expand_env_variable(Value, Key, ""); {ok, Value0} -> %% Use previous definition in expansion @@ -283,16 +304,17 @@ expand_vars_loop(Vars0, Count) -> %% Expand all OTHER references to a given K/V pair %% expand_vars(Key, Value, Vars) -> - lists:foldl(fun({AKey, AValue}, Acc) -> - case AKey of - Key -> - NewValue = AValue; - _ -> - NewValue = expand_env_variable(AValue, Key, Value) - end, - [{AKey, NewValue} | Acc] - end, - [], Vars). + lists:foldl( + fun({AKey, AValue}, Acc) -> + case AKey of + Key -> + NewValue = AValue; + _ -> + NewValue = expand_env_variable(AValue, Key, Value) + end, + [{AKey, NewValue} | Acc] + end, + [], Vars). %% @@ -325,7 +347,8 @@ erts_dir() -> lists:concat([code:root_dir(), "/erts-", erlang:system_info(version)]). os_env() -> - Os = [list_to_tuple(re:split(S, "=", [{return, list}, {parts, 2}])) || S <- os:getenv()], + Os = [list_to_tuple(re:split(S, "=", [{return, list}, {parts, 2}])) || + S <- os:getenv()], lists:keydelete([],1,Os). %% Remove Windows current disk and path default_env() -> @@ -339,7 +362,8 @@ default_env() -> " -lerl_interface -lei"])}, {"DRV_CFLAGS", "-g -Wall -fPIC $ERL_CFLAGS"}, {"DRV_LDFLAGS", "-shared $ERL_LDFLAGS"}, - {"darwin", "DRV_LDFLAGS", "-bundle -flat_namespace -undefined suppress $ERL_LDFLAGS"}, + {"darwin", "DRV_LDFLAGS", + "-bundle -flat_namespace -undefined suppress $ERL_LDFLAGS"}, {"ERLANG_ARCH", integer_to_list(8 * erlang:system_info(wordsize))}, {"ERLANG_TARGET", rebar_utils:get_arch()}, @@ -383,13 +407,13 @@ switch_so_to_dll(Orig = {Name, Spec}) -> make_so_specs(Config, AppFile, Bins) -> case rebar_config:get(Config, so_specs, undefined) of undefined -> - %% New form of so_specs is not provided. See if the old form of {so_name} is available - %% instead + %% New form of so_specs is not provided. See if the old form + %% of {so_name} is available instead Dir = "priv", SoName = case rebar_config:get(Config, so_name, undefined) of undefined -> - %% Ok, neither old nor new form is available. Use the app name and - %% generate a sensible default. + %% Ok, neither old nor new form is available. Use + %% the app name and generate a sensible default. AppName = rebar_app_utils:app_name(AppFile), filename:join(Dir, lists:concat([AppName, "_drv.so"])); diff --git a/src/rebar_protobuffs_compiler.erl b/src/rebar_protobuffs_compiler.erl index 8ad0318..421b258 100644 --- a/src/rebar_protobuffs_compiler.erl +++ b/src/rebar_protobuffs_compiler.erl @@ -40,8 +40,8 @@ compile(_Config, _AppFile) -> [] -> ok; FoundFiles -> - %% Check for protobuffs library -- if it's not present, fail since we have - %% .proto files that need building + %% Check for protobuffs library -- if it's not present, fail + %% since we have.proto files that need building case protobuffs_is_present() of true -> %% Build a list of output files - { Proto, Beam, Hrl } @@ -51,7 +51,8 @@ compile(_Config, _AppFile) -> %% Compile each proto file compile_each(Targets); false -> - ?ERROR("Protobuffs library not present in code path!\n", []), + ?ERROR("Protobuffs library not present in code path!\n", + []), ?FAIL end end. @@ -60,7 +61,9 @@ compile(_Config, _AppFile) -> clean(_Config, _AppFile) -> %% Get a list of generated .beam and .hrl files and then delete them Protos = filelib:wildcard("src/*.proto"), - Targets = [fq_beam_file(F) || F <- Protos] ++ [fq_hrl_file(F) || F <- Protos], + BeamFiles = [fq_beam_file(F) || F <- Protos], + HrlFiles = [fq_hrl_file(F) || F <- Protos], + Targets = BeamFiles ++ HrlFiles, case Targets of [] -> ok; @@ -100,16 +103,18 @@ compile_each([{Proto, Beam, Hrl} | Rest]) -> ?CONSOLE("Compiling ~s\n", [Proto]), case protobuffs_compile:scan_file(Proto) of ok -> - %% Compilation worked, but we need to move the .beam and .hrl file - %% into the ebin/ and include/ directories respectively - %% TODO: Protobuffs really needs to be better about this...sigh. + %% Compilation worked, but we need to move the + %% beam and .hrl file into the ebin/ and include/ + %% directories respectively + %% TODO: Protobuffs really needs to be better about this ok = filelib:ensure_dir(filename:join("ebin","dummy")), ok = rebar_file_utils:mv(Beam, "ebin"), ok = filelib:ensure_dir(filename:join("include", Hrl)), ok = rebar_file_utils:mv(Hrl, "include"), ok; Other -> - ?ERROR("Protobuff compile of ~s failed: ~p\n", [Proto, Other]), + ?ERROR("Protobuff compile of ~s failed: ~p\n", + [Proto, Other]), ?FAIL end; false -> diff --git a/src/rebar_reltool.erl b/src/rebar_reltool.erl index dc19538..5cbd587 100644 --- a/src/rebar_reltool.erl +++ b/src/rebar_reltool.erl @@ -78,13 +78,14 @@ clean(_Config, ReltoolFile) -> check_vsn() -> case code:lib_dir(reltool) of {error, bad_name} -> - ?ABORT("Reltool support requires the reltool application to be installed!", []); + ?ABORT("Reltool support requires the reltool application " + "to be installed!", []); Path -> ReltoolVsn = filename:basename(Path), case ReltoolVsn < "reltool-0.5.2" of true -> - ?ABORT("Reltool support requires at least reltool-0.5.2; this VM is using ~s\n", - [ReltoolVsn]); + ?ABORT("Reltool support requires at least reltool-0.5.2; " + "this VM is using ~s\n", [ReltoolVsn]); false -> ok end @@ -98,12 +99,13 @@ load_config(ReltoolFile) -> {ok, Terms} -> Terms; Other -> - ?ABORT("Failed to load expected config from ~s: ~p\n", [ReltoolFile, 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. +%% 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 @@ -160,15 +162,17 @@ validate_rel_apps(ReltoolServer, {sys, ReltoolConfig}) -> false -> ok; {rel, _Name, _Vsn, Apps} -> - %% Identify all the apps that do NOT exist, based on what's available - %% from the reltool server - Missing = lists:sort([App || App <- Apps, - app_exists(App, ReltoolServer) == false]), + %% Identify all the apps that do NOT exist, based on + %% what's available from the reltool server + Missing = lists:sort( + [App || App <- Apps, + app_exists(App, ReltoolServer) == false]), case Missing of [] -> ok; _ -> - ?ABORT("Apps in {rel, ...} section not found by reltool: ~p\n", [Missing]) + ?ABORT("Apps in {rel, ...} section not found by " + "reltool: ~p\n", [Missing]) end; Rel -> %% Invalid release format! @@ -201,10 +205,12 @@ run_reltool(Server, _Config, ReltoolConfig) -> ok -> ok; {error, Reason} -> - ?ABORT("Failed to generate target from spec: ~p\n", [Reason]) + ?ABORT("Failed to generate target from spec: ~p\n", + [Reason]) end, - %% Initialize overlay vars with some basics (that can get overwritten) + %% Initialize overlay vars with some basics + %% (that can get overwritten) OverlayVars0 = [{erts_vsn, "erts-" ++ erlang:system_info(version)}], %% Load up any variables specified by overlay_vars @@ -216,7 +222,8 @@ run_reltool(Server, _Config, ReltoolConfig) -> {ok, Terms} -> dict:from_list(OverlayVars0 ++ Terms); {error, Reason2} -> - ?ABORT("Unable to load overlay_vars from ~s: ~p\n", + ?ABORT("Unable to load overlay_vars " + "from ~s: ~p\n", [File, Reason2]) end end, @@ -249,7 +256,8 @@ mk_target_dir(TargetDir) -> rebar_file_utils:rm_rf(TargetDir), ok = file:make_dir(TargetDir); _ -> - ?ERROR("Release target directory ~p already exists!\n", [TargetDir]), + ?ERROR("Release target directory ~p already exists!\n", + [TargetDir]), ?FAIL end end. @@ -310,12 +318,14 @@ execute_overlay([{create, Out, Contents} | Rest], Vars, BaseDir, TargetDir) -> end; execute_overlay([{replace, Out, Regex, Replacement} | Rest], Vars, BaseDir, TargetDir) -> - execute_overlay([{replace, Out, Regex, Replacement, []} | Rest], Vars, BaseDir, TargetDir); + execute_overlay([{replace, Out, Regex, Replacement, []} | Rest], + Vars, BaseDir, TargetDir); execute_overlay([{replace, Out, Regex, Replacement, Opts} | Rest], Vars, BaseDir, TargetDir) -> Filename = render(filename:join(TargetDir, Out), Vars), {ok, OrigData} = file:read_file(Filename), - Data = re:replace(OrigData, Regex, Replacement, [global, {return, binary}] ++ Opts), + Data = re:replace(OrigData, Regex, Replacement, + [global, {return, binary}] ++ Opts), case file:write_file(Filename, Data) of ok -> ?DEBUG("Edited ~s: s/~s/~s/\n", [Filename, Regex, Replacement]), diff --git a/src/rebar_require_vsn.erl b/src/rebar_require_vsn.erl index 0f428a1..a9991e9 100644 --- a/src/rebar_require_vsn.erl +++ b/src/rebar_require_vsn.erl @@ -64,6 +64,3 @@ check_versions(Config) -> ?ABORT("OTP release ~s does not match required regex ~s\n", [erlang:system_info(otp_release), OtpRegex]) end. - - - diff --git a/src/rebar_subdirs.erl b/src/rebar_subdirs.erl index abae853..b107978 100644 --- a/src/rebar_subdirs.erl +++ b/src/rebar_subdirs.erl @@ -37,6 +37,6 @@ 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, [])], + Subdirs = [filename:join(Cwd, Dir) || + Dir <- rebar_config:get_local(Config, sub_dirs, [])], {ok, Subdirs}. - diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl index 7716066..487a578 100644 --- a/src/rebar_templater.erl +++ b/src/rebar_templater.erl @@ -99,13 +99,13 @@ create(_Config, _) -> ok end; false -> - ?WARN("No variables section found in template ~p; using empty context.\n", - [TemplateId]), + ?WARN("No variables section found in template ~p; " + "using empty context.\n", [TemplateId]), Context0 = dict:new() end, - %% For each variable, see if it's defined in global vars -- if it is, prefer that - %% value over the defaults + %% For each variable, see if it's defined in global vars -- if it is, + %% prefer that value over the defaults Context1 = update_vars(dict:fetch_keys(Context0), Context0), ?DEBUG("Template ~p context: ~p\n", [TemplateId, dict:to_list(Context1)]), @@ -113,10 +113,11 @@ create(_Config, _) -> %% definition Context = resolve_recursive_vars(dict:to_list(Context1), Context1), - ?DEBUG("Resolved Template ~p context: ~p\n", [TemplateId, dict:to_list(Context1)]), + ?DEBUG("Resolved Template ~p context: ~p\n", + [TemplateId, dict:to_list(Context1)]), - %% Now, use our context to process the template definition -- this permits us to - %% use variables within the definition for filenames. + %% Now, use our context to process the template definition -- this + %% permits us to use variables within the definition for filenames. FinalTemplate = consult(render(load_file(Type, Template), Context)), ?DEBUG("Final template def ~p: ~p\n", [TemplateId, FinalTemplate]), @@ -136,10 +137,10 @@ create(_Config, _) -> %% cache_escript_files() -> {ok, Files} = rebar_utils:escript_foldl( - fun(Name, _, GetBin, Acc) -> - [{Name, GetBin()} | Acc] - end, - [], rebar_config:get_global(escript, undefined)), + fun(Name, _, GetBin, Acc) -> + [{Name, GetBin()} | Acc] + end, + [], rebar_config:get_global(escript, undefined)), erlang:put(escript_files, Files). @@ -158,7 +159,8 @@ find_escript_templates() -> find_disk_templates() -> OtherTemplates = find_other_templates(), HomeFiles = rebar_utils:find_files(filename:join(os:getenv("HOME"), - ".rebar/templates"), ?TEMPLATE_RE), + ".rebar/templates"), + ?TEMPLATE_RE), LocalFiles = rebar_utils:find_files(".", ?TEMPLATE_RE), [{file, F} || F <- OtherTemplates ++ HomeFiles ++ LocalFiles]. @@ -289,18 +291,24 @@ write_file(Output, Data, Force) -> %% %% Execute each instruction in a template definition file. %% -execute_template([], _TemplateType, _TemplateName, _Context, _Force, ExistingFiles) -> +execute_template([], _TemplateType, _TemplateName, _Context, + _Force, ExistingFiles) -> case ExistingFiles of [] -> ok; _ -> - Msg = lists:flatten([io_lib:format("\t* ~p~n", [F]) || F <- lists:reverse(ExistingFiles)]), - Help = "To force overwriting, specify force=1 on the command line.\n", - ?ERROR("One or more files already exist on disk and were not generated:~n~s~s", [Msg , Help]) + Msg = lists:flatten([io_lib:format("\t* ~p~n", [F]) || + F <- lists:reverse(ExistingFiles)]), + Help = + "To force overwriting, specify force=1 on the command line.\n", + ?ERROR("One or more files already exist on disk and " + "were not generated:~n~s~s", [Msg , Help]) end; -execute_template([{template, Input, Output} | Rest], TemplateType, TemplateName, Context, Force, ExistingFiles) -> +execute_template([{template, Input, Output} | Rest], TemplateType, + TemplateName, Context, Force, ExistingFiles) -> InputName = filename:join(filename:dirname(TemplateName), Input), - case write_file(Output, render(load_file(TemplateType, InputName), Context), Force) of + case write_file(Output, render(load_file(TemplateType, InputName), Context), + Force) of ok -> execute_template(Rest, TemplateType, TemplateName, Context, Force, ExistingFiles); @@ -308,34 +316,43 @@ execute_template([{template, Input, Output} | Rest], TemplateType, TemplateName, execute_template(Rest, TemplateType, TemplateName, Context, Force, [Output|ExistingFiles]) end; -execute_template([{file, Input, Output} | Rest], TemplateType, TemplateName, Context, Force, ExistingFiles) -> +execute_template([{file, Input, Output} | Rest], TemplateType, TemplateName, + Context, Force, ExistingFiles) -> InputName = filename:join(filename:dirname(TemplateName), Input), case write_file(Output, load_file(TemplateType, InputName), Force) of ok -> - execute_template(Rest, TemplateType, TemplateName, Context, - Force, ExistingFiles); + execute_template(Rest, TemplateType, TemplateName, + Context, Force, ExistingFiles); {error, exists} -> - execute_template(Rest, TemplateType, TemplateName, Context, - Force, [Output|ExistingFiles]) + execute_template(Rest, TemplateType, TemplateName, + Context, Force, [Output|ExistingFiles]) end; -execute_template([{dir, Name} | Rest], TemplateType, TemplateName, Context, Force, ExistingFiles) -> +execute_template([{dir, Name} | Rest], TemplateType, TemplateName, Context, + Force, ExistingFiles) -> case filelib:ensure_dir(filename:join(Name, "dummy")) of ok -> - execute_template(Rest, TemplateType, TemplateName, Context, Force, ExistingFiles); + execute_template(Rest, TemplateType, TemplateName, + Context, Force, ExistingFiles); {error, Reason} -> - ?ABORT("Failed while processing template instruction {dir, ~s}: ~p\n", - [Name, Reason]) + ?ABORT("Failed while processing template instruction " + "{dir, ~s}: ~p\n", [Name, Reason]) end; -execute_template([{chmod, Mod, File} | Rest], TemplateType, TemplateName, Context, Force, ExistingFiles) when is_integer(Mod) -> +execute_template([{chmod, Mod, File} | Rest], TemplateType, TemplateName, + Context, Force, ExistingFiles) when is_integer(Mod) -> case file:change_mode(File, Mod) of ok -> - execute_template(Rest, TemplateType, TemplateName, Context, Force, ExistingFiles); + execute_template(Rest, TemplateType, TemplateName, + Context, Force, ExistingFiles); {error, Reason} -> - ?ABORT("Failed while processing template instruction {cmod, ~b, ~s}: ~p~n", - [Mod, File, Reason]) + ?ABORT("Failed while processing template instruction " + "{cmod, ~b, ~s}: ~p~n", [Mod, File, Reason]) end; -execute_template([{variables, _} | Rest], TemplateType, TemplateName, Context, Force, ExistingFiles) -> - execute_template(Rest, TemplateType, TemplateName, Context, Force, ExistingFiles); -execute_template([Other | Rest], TemplateType, TemplateName, Context, Force, ExistingFiles) -> +execute_template([{variables, _} | Rest], TemplateType, TemplateName, Context, + Force, ExistingFiles) -> + execute_template(Rest, TemplateType, TemplateName, + Context, Force, ExistingFiles); +execute_template([Other | Rest], TemplateType, TemplateName, Context, + Force, ExistingFiles) -> ?WARN("Skipping unknown template instruction: ~p\n", [Other]), - execute_template(Rest, TemplateType, TemplateName, Context, Force, ExistingFiles). + execute_template(Rest, TemplateType, TemplateName, Context, + Force, ExistingFiles). diff --git a/src/rebar_upgrade.erl b/src/rebar_upgrade.erl index c882cc8..639ddef 100644 --- a/src/rebar_upgrade.erl +++ b/src/rebar_upgrade.erl @@ -159,10 +159,12 @@ run_systools(NewVer, Name) -> boot_files(Ver, Name) -> ok = file:make_dir(filename:join([".", "releases"])), ok = file:make_dir(filename:join([".", "releases", Ver])), - ok = file:make_symlink(filename:join(["start.boot"]), - filename:join([".", "releases", Ver, Name ++ ".boot"])), - {ok, _} = file:copy(filename:join([".", Name, "releases", Ver, "start_clean.boot"]), - filename:join([".", "releases", Ver, "start_clean.boot"])). + ok = file:make_symlink( + filename:join(["start.boot"]), + filename:join([".", "releases", Ver, Name ++ ".boot"])), + {ok, _} = file:copy( + filename:join([".", Name, "releases", Ver, "start_clean.boot"]), + filename:join([".", "releases", Ver, "start_clean.boot"])). make_tar(NameVer) -> Filename = NameVer ++ ".tar.gz", diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index aa324c2..c8eccc4 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -113,7 +113,7 @@ find_files(Dir, Regex) -> now_str() -> {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:local_time(), lists:flatten(io_lib:format("~4b/~2..0b/~2..0b ~2..0b:~2..0b:~2..0b", - [Year, Month, Day, Hour, Minute, Second])). + [Year, Month, Day, Hour, Minute, Second])). %% TODO: filelib:ensure_dir/1 corrected in R13B04. Remove when we drop %% support for OTP releases older than R13B04. diff --git a/src/rebar_xref.erl b/src/rebar_xref.erl index 8a489a8..f46ccfc 100644 --- a/src/rebar_xref.erl +++ b/src/rebar_xref.erl @@ -44,8 +44,11 @@ xref(Config, _) -> %% Spin up xref {ok, _} = xref:start(xref), ok = xref:set_library_path(xref, code_path()), - xref:set_default(xref, [{warnings, rebar_config:get(Config, xref_warnings, false)}, + + xref:set_default(xref, [{warnings, + rebar_config:get(Config, xref_warnings, false)}, {verbose, rebar_config:is_verbose()}]), + {ok, _} = xref:add_directory(xref, "ebin"), %% Save the code path prior to doing anything @@ -53,8 +56,9 @@ xref(Config, _) -> true = code:add_path(filename:join(rebar_utils:get_cwd(), "ebin")), %% Get list of xref checks we want to run - XrefChecks = rebar_config:get(Config, xref_checks, [exports_not_used, - undefined_function_calls]), + XrefChecks = rebar_config:get(Config, xref_checks, + [exports_not_used, + undefined_function_calls]), %% Look for exports that are unused by anything case lists:member(exports_not_used, XrefChecks) of @@ -91,12 +95,15 @@ check_exports_not_used(_Config) -> check_undefined_function_calls(_Config) -> {ok, UndefinedCalls0} = xref:analyze(xref, undefined_function_calls), - UndefinedCalls = [{find_mfa_source(Caller), format_fa(Caller), format_mfa(Target)} || - {Caller, Target} <- UndefinedCalls0], - lists:foreach(fun({{Source, Line}, FunStr, Target}) -> - ?CONSOLE("~s:~w: Warning ~s calls undefined function ~s\n", - [Source, Line, FunStr, Target]) - end, UndefinedCalls), + UndefinedCalls = + [{find_mfa_source(Caller), format_fa(Caller), format_mfa(Target)} || + {Caller, Target} <- UndefinedCalls0], + + lists:foreach( + fun({{Source, Line}, FunStr, Target}) -> + ?CONSOLE("~s:~w: Warning ~s calls undefined function ~s\n", + [Source, Line, FunStr, Target]) + end, UndefinedCalls), ok. @@ -112,15 +119,18 @@ filter_away_ignored(UnusedExports) -> %% -ignore_xref([{F, A}, ...]). %% Setup a filter function that builds a list of behaviour callbacks and/or - %% any functions marked to ignore. We then use this list to mask any functions - %% marked as unused exports by xref + %% any functions marked to ignore. We then use this list to mask any + %% functions marked as unused exports by xref F = fun(Mod) -> Attrs = kf(attributes, Mod:module_info()), Ignore = kf(ignore_xref, Attrs), - Callbacks = [B:behaviour_info(callbacks) || B <- kf(behaviour, Attrs)], + Callbacks = + [B:behaviour_info(callbacks) || B <- kf(behaviour, Attrs)], [{Mod, F, A} || {F, A} <- Ignore ++ lists:flatten(Callbacks)] end, - AttrIgnore = lists:flatten(lists:map(F, lists:usort([M || {M, _, _} <- UnusedExports]))), + AttrIgnore = + lists:flatten( + lists:map(F, lists:usort([M || {M, _, _} <- UnusedExports]))), [X || X <- UnusedExports, not lists:member(X, AttrIgnore)]. @@ -136,7 +146,8 @@ display_mfas([], _Message) -> ok; display_mfas([{_Mod, Fun, Args} = MFA | Rest], Message) -> {Source, Line} = find_mfa_source(MFA), - ?CONSOLE("~s:~w: Warning: function ~s/~w ~s\n", [Source, Line, Fun, Args, Message]), + ?CONSOLE("~s:~w: Warning: function ~s/~w ~s\n", + [Source, Line, Fun, Args, Message]), display_mfas(Rest, Message). format_mfa({M, F, A}) -> @@ -164,8 +175,8 @@ safe_element(N, Tuple) -> %% find_mfa_source({M, F, A}) -> {M, Bin, _} = code:get_object_code(M), - {ok, {M, [{abstract_code, AbstractCode}]}} = beam_lib:chunks(Bin, [abstract_code]), - {raw_abstract_v1, Code} = AbstractCode, + AbstractCode = beam_lib:chunks(Bin, [abstract_code]), + {ok, {M, [{abstract_code, {raw_abstract_v1, Code}}]}} = AbstractCode, %% Extract the original source filename from the abstract code [{attribute, 1, file, {Source, _}} | _] = Code, %% Extract the line number for a given function def -- cgit v1.1 From 3241165ced709246935701f0b638d759e54316a2 Mon Sep 17 00:00:00 2001 From: David Reid Date: Mon, 7 Feb 2011 15:32:12 -0800 Subject: Support 2 forms of implicit HEAD for git In git origin/HEAD is a pointer to the default branch. This patch allows two alternatives to explicitly specifying "HEAD" in git VC specs. The first is a 2 arity form {git, Url} and the second is {git, Url, ""} which worked in pre-update-deps rebars. --- src/rebar_deps.erl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl index 99ede3d..69f5fc1 100644 --- a/src/rebar_deps.erl +++ b/src/rebar_deps.erl @@ -303,6 +303,10 @@ download_source(AppDir, {hg, Url, Rev}) -> rebar_utils:sh(?FMT("hg clone -U ~s ~s", [Url, filename:basename(AppDir)]), [{cd, filename:dirname(AppDir)}]), rebar_utils:sh(?FMT("hg update ~s", [Rev]), [{cd, AppDir}]); +download_source(AppDir, {git, Url}) -> + download_source(AppDir, {git, Url, "HEAD"}); +download_source(AppDir, {git, Url, ""}) -> + download_source(AppDir, {git, Url, "HEAD"}); download_source(AppDir, {git, Url, {branch, Branch}}) -> ok = filelib:ensure_dir(AppDir), rebar_utils:sh(?FMT("git clone -n ~s ~s", [Url, filename:basename(AppDir)]), @@ -344,6 +348,10 @@ update_source(Dep) -> Dep end. +update_source(AppDir, {git, Url}) -> + update_source(AppDir, {git, Url, "HEAD"}); +update_source(AppDir, {git, Url, ""}) -> + update_source(AppDir, {git, Url, "HEAD"}); update_source(AppDir, {git, _Url, {branch, Branch}}) -> ShOpts = [{cd, AppDir}], rebar_utils:sh("git fetch origin", ShOpts), -- cgit v1.1 From e4cd50e2a356702dca433dc23510b5170de860f2 Mon Sep 17 00:00:00 2001 From: Joseph Wayne Norton Date: Thu, 16 Dec 2010 16:14:08 +0100 Subject: Add eunit_first_files option --- src/rebar_eunit.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl index 01fb805..4790869 100644 --- a/src/rebar_eunit.erl +++ b/src/rebar_eunit.erl @@ -189,7 +189,10 @@ eunit_config(Config) -> EunitOpts = rebar_config:get_list(Config, eunit_compile_opts, []), Opts = [{d, 'TEST'}, debug_info] ++ ErlOpts ++ EunitOpts ++ EqcOpts, - rebar_config:set(Config, erl_opts, Opts). + Config1 = rebar_config:set(Config, erl_opts, Opts), + + FirstErls = rebar_config:get_list(Config1, eunit_first_files, []), + rebar_config:set(Config1, erl_first_files, FirstErls). is_quickcheck_avail() -> case erlang:get(is_quickcheck_avail) of -- cgit v1.1 From b70f374f897585b2f465e9f1c37ad18ea885dded Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sun, 13 Feb 2011 16:35:03 +0100 Subject: Remove export_all directive --- src/rebar_eunit.erl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl index 4790869..28aeaf1 100644 --- a/src/rebar_eunit.erl +++ b/src/rebar_eunit.erl @@ -43,9 +43,8 @@ %% ------------------------------------------------------------------- -module(rebar_eunit). --export([eunit/2]). - --compile([export_all]). +-export([eunit/2, + clean/2]). -include("rebar.hrl"). -- cgit v1.1 From e407838bab16038951a4f5489bdf8737116c775d Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sun, 13 Feb 2011 18:11:29 +0100 Subject: Document eunit_first_files --- rebar.config.sample | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rebar.config.sample b/rebar.config.sample index 8954c15..184c16d 100644 --- a/rebar.config.sample +++ b/rebar.config.sample @@ -86,6 +86,9 @@ %% Additional compile options for eunit. erl_opts from above is also used {eunit_compile_opts, []}. +%% Same as erl_first_files, but used only when running 'eunit' +{eunit_first_files, []}. + %% Whether to enable coverage reporting. Default is `false' {cover_enabled, false}. -- cgit v1.1 From 1979da9ee21b90799bdbd3f2b5cdec5e5c982a01 Mon Sep 17 00:00:00 2001 From: Joseph Wayne Norton Date: Sat, 12 Feb 2011 23:50:12 +0900 Subject: Clarify trailing slash for PIPE_DIR The trailing slash for PIPE_DIR is necessary for both start and attach operations. --- priv/templates/simplenode.runner | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/priv/templates/simplenode.runner b/priv/templates/simplenode.runner index ec6d7ff..18fa951 100755 --- a/priv/templates/simplenode.runner +++ b/priv/templates/simplenode.runner @@ -7,6 +7,7 @@ RUNNER_SCRIPT_DIR=$(cd ${0%/*} && pwd) RUNNER_BASE_DIR=${RUNNER_SCRIPT_DIR%/*} RUNNER_ETC_DIR=$RUNNER_BASE_DIR/etc RUNNER_LOG_DIR=$RUNNER_BASE_DIR/log +# Note the trailing slash on $PIPE_DIR/ PIPE_DIR=/tmp/$RUNNER_BASE_DIR/ RUNNER_USER= @@ -61,8 +62,7 @@ case "$1" in HEART_COMMAND="$RUNNER_BASE_DIR/bin/$SCRIPT start" export HEART_COMMAND mkdir -p $PIPE_DIR - # Note the trailing slash on $PIPE_DIR/ - $ERTS_PATH/run_erl -daemon $PIPE_DIR/ $RUNNER_LOG_DIR "exec $RUNNER_BASE_DIR/bin/$SCRIPT console" 2>&1 + $ERTS_PATH/run_erl -daemon $PIPE_DIR $RUNNER_LOG_DIR "exec $RUNNER_BASE_DIR/bin/$SCRIPT console" 2>&1 ;; stop) -- cgit v1.1 From 7810d7bf7cebe7062c5850b5f20eeb12cf5e3284 Mon Sep 17 00:00:00 2001 From: Tim Watson Date: Wed, 26 Jan 2011 11:57:22 +0000 Subject: Add common_test suite template This change adds a simple common_test suite template that can be instantiated with the name of a module under test like so: `rebar create template=ctsuite testmod=mymodule` The template creates an empty test suite in the test directory, automatically exports test functions and sets up a first, skipped test function. --- priv/templates/ctsuite.erl | 167 ++++++++++++++++++++++++++++++++++++++++ priv/templates/ctsuite.template | 2 + 2 files changed, 169 insertions(+) create mode 100644 priv/templates/ctsuite.erl create mode 100644 priv/templates/ctsuite.template diff --git a/priv/templates/ctsuite.erl b/priv/templates/ctsuite.erl new file mode 100644 index 0000000..b8fdfe7 --- /dev/null +++ b/priv/templates/ctsuite.erl @@ -0,0 +1,167 @@ +%% common_test suite for {{testmod}} + +-module({{testmod}}_SUITE). +-include_lib("common_test/include/ct.hrl"). + +-compile(export_all). + +%%-------------------------------------------------------------------- +%% Function: suite() -> Info +%% +%% Info = [tuple()] +%% List of key/value pairs. +%% +%% Description: Returns list of tuples to set default properties +%% for the suite. +%% +%% Note: The suite/0 function is only meant to be used to return +%% default data values, not perform any other operations. +%%-------------------------------------------------------------------- +suite() -> [{timetrap, {seconds, 20}}]. + +%%-------------------------------------------------------------------- +%% Function: groups() -> [Group] +%% +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% The name of the group. +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% Group properties that may be combined. +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% The name of a test case. +%% Shuffle = shuffle | {shuffle,Seed} +%% To get cases executed in random order. +%% Seed = {integer(),integer(),integer()} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% To get execution of cases repeated. +%% N = integer() | forever +%% +%% Description: Returns a list of test case group definitions. +%%-------------------------------------------------------------------- +groups() -> []. + +%%-------------------------------------------------------------------- +%% Function: all() -> GroupsAndTestCases +%% +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% Name of a test case group. +%% TestCase = atom() +%% Name of a test case. +%% +%% Description: Returns the list of groups and test cases that +%% are to be executed. +%% +%% NB: By default, we export all 1-arity user defined functions +%%-------------------------------------------------------------------- +all() -> + [ {exports, Functions} | _ ] = ?MODULE:module_info(), + [ FName || {FName, _} <- lists:filter( + fun ({module_info,_}) -> false ; + ({all,_}) -> false ; + ({init_per_suite,1}) -> false ; + ({end_per_suite,1}) -> false ; + ({_,1}) -> true ; + ({_,_}) -> false + end, Functions)]. + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% +%% Config0 = Config1 = [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Reason = term() +%% The reason for skipping the suite. +%% +%% Description: Initialization before the suite. +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config0) -> void() | {save_config,Config1} +%% +%% Config0 = Config1 = [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Description: Cleanup after the suite. +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% +%% GroupName = atom() +%% Name of the test case group that is about to run. +%% Config0 = Config1 = [tuple()] +%% A list of key/value pairs, holding configuration data for the group. +%% Reason = term() +%% The reason for skipping all test cases and subgroups in the group. +%% +%% Description: Initialization before each test case group. +%%-------------------------------------------------------------------- +init_per_group(_group, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% +%% GroupName = atom() +%% Name of the test case group that is finished. +%% Config0 = Config1 = [tuple()] +%% A list of key/value pairs, holding configuration data for the group. +%% +%% Description: Cleanup after each test case group. +%%-------------------------------------------------------------------- +end_per_group(_group, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% +%% TestCase = atom() +%% Name of the test case that is about to run. +%% Config0 = Config1 = [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Reason = term() +%% The reason for skipping the test case. +%% +%% Description: Initialization before each test case. +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%%-------------------------------------------------------------------- +init_per_testcase(TestCase, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config0) -> +%% void() | {save_config,Config1} | {fail,Reason} +%% +%% TestCase = atom() +%% Name of the test case that is finished. +%% Config0 = Config1 = [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Reason = term() +%% The reason for failing the test case. +%% +%% Description: Cleanup after each test case. +%%-------------------------------------------------------------------- +end_per_testcase(TestCase, Config) -> + Config. + +test_{{testmod}}() -> + [{userdata,[{doc,"Testing the {{testmod}} module"}]}]. + +test_{{testmod}}(_Config) -> + {skip,"Not implemented."}. diff --git a/priv/templates/ctsuite.template b/priv/templates/ctsuite.template new file mode 100644 index 0000000..b7de337 --- /dev/null +++ b/priv/templates/ctsuite.template @@ -0,0 +1,2 @@ +{variables, [{testmod, "mymodule"}]}. +{template, "ctsuite.erl", "test/{{testmod}}_SUITE.erl"}. -- cgit v1.1 From 1b1080719399cc952d244fbe68b0e53bc3e213d3 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Tue, 15 Feb 2011 17:26:01 +0100 Subject: Remove gratuitous spaces --- priv/templates/ctsuite.erl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/priv/templates/ctsuite.erl b/priv/templates/ctsuite.erl index b8fdfe7..33a8fac 100644 --- a/priv/templates/ctsuite.erl +++ b/priv/templates/ctsuite.erl @@ -59,11 +59,11 @@ groups() -> []. all() -> [ {exports, Functions} | _ ] = ?MODULE:module_info(), [ FName || {FName, _} <- lists:filter( - fun ({module_info,_}) -> false ; - ({all,_}) -> false ; - ({init_per_suite,1}) -> false ; - ({end_per_suite,1}) -> false ; - ({_,1}) -> true ; + fun ({module_info,_}) -> false; + ({all,_}) -> false; + ({init_per_suite,1}) -> false; + ({end_per_suite,1}) -> false; + ({_,1}) -> true; ({_,_}) -> false end, Functions)]. -- cgit v1.1 From 9ee8ed91812f22e6e84887ba006f3a5c37457fcc Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 15 Feb 2011 01:51:35 +0100 Subject: Give an absolute path to code:add_path/1 If an app uses -include_lib for its own included files, compilation fails if the app directory isn't in $ERL_LIBS because code:lib_dir/1 will return an error. An absolute path needs to be added to code path instead of just "ebin". --- src/rebar_erlc_compiler.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 7f02e89..df9e1c0 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -152,7 +152,7 @@ doterl_compile(Config, OutDir, MoreSources) -> %% Make sure that ebin/ exists and is on the path ok = filelib:ensure_dir(filename:join("ebin", "dummy.beam")), CurrPath = code:get_path(), - true = code:add_path("ebin"), + true = code:add_path(filename:absname("ebin")), rebar_base_compiler:run(Config, NewFirstErls, OtherErls, fun(S, C) -> internal_erl_compile(S, C, OutDir, ErlOpts) -- cgit v1.1 From 11bf6b4aab33c273f0db94bded8763af68cbc167 Mon Sep 17 00:00:00 2001 From: joewilliams Date: Thu, 10 Feb 2011 13:27:29 -0800 Subject: Add 'generate-appups' command To further support OTP releases I have added support for generating application appup files. These include instructions that systools uses to generate a relup file which contains the low level instructions needed to perform a hot code upgrade. My goal with this module is to produce "good enough" appup files or at least a skeleton to help one get started with something more complex. If an appup file already exists for an application this command will not attempt to create a new one. Usage: $ rebar generate-appups previous_release=/path/to/old/version Generally this command will be run just before 'generate-upgrade'. --- ebin/rebar.app | 2 + src/rebar.erl | 6 +- src/rebar_appups.erl | 185 +++++++++++++++++++++++ src/rebar_utils.erl | 42 ++++- test/upgrade_project/README.md | 1 + test/upgrade_project/apps/dummy/ebin/dummy.appup | 8 - 6 files changed, 233 insertions(+), 11 deletions(-) create mode 100644 src/rebar_appups.erl delete mode 100644 test/upgrade_project/apps/dummy/ebin/dummy.appup diff --git a/ebin/rebar.app b/ebin/rebar.app index 1f7db21..a99df4e 100644 --- a/ebin/rebar.app +++ b/ebin/rebar.app @@ -3,6 +3,7 @@ {vsn, "2"}, {modules, [ rebar, rebar_abnfc_compiler, + rebar_appups, rebar_app_utils, rebar_base_compiler, rebar_config, @@ -80,6 +81,7 @@ ]}, {rel_dir, [ + rebar_appups, rebar_reltool, rebar_upgrade ]} diff --git a/src/rebar.erl b/src/rebar.erl index 22f2080..b83a1f7 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -224,6 +224,8 @@ generate [dump_spec=0/1] Build release with reltool generate-upgrade previous_release=path Build an upgrade package +generate-appups previous_release=path Generate appup files + eunit [suite=foo] Run eunit [test/foo_tests.erl] tests ct [suite=] [case=] Run common_test suites in ./test @@ -277,8 +279,8 @@ filter_flags([Item | Rest], Commands) -> command_names() -> ["build-plt", "check-deps", "check-plt", "clean", "compile", "create", "create-app", "create-node", "ct", "delete-deps", "dialyze", "doc", - "eunit", "generate", "generate-upgrade", "get-deps", "help", - "list-templates", "update-deps", "version", "xref"]. + "eunit", "generate", "generate-appups", "generate-upgrade", "get-deps", + "help", "list-templates", "update-deps", "version", "xref"]. unabbreviate_command_names([]) -> []; diff --git a/src/rebar_appups.erl b/src/rebar_appups.erl new file mode 100644 index 0000000..e7333fd --- /dev/null +++ b/src/rebar_appups.erl @@ -0,0 +1,185 @@ +%% -*- 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]). + +-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 + OldVerPath = rebar_utils:get_previous_release_path(), + + %% Get the new and old release name and versions + {Name, _Ver} = rebar_utils:get_reltool_release_info(ReltoolFile), + NewVerPath = filename:join([".", Name]), + {NewName, NewVer} = rebar_utils:get_rel_release_info(Name, NewVerPath), + {OldName, OldVer} = rebar_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", []), + + %% Get lists of the old and new app files + OldAppFiles = rebar_utils:find_files( + filename:join([OldVerPath, "lib"]), "^.*.app$"), + NewAppFiles = rebar_utils:find_files( + filename:join([NewName, "lib"]), "^.*.app$"), + + %% Find all the apps that have been upgraded + UpgradedApps = get_upgraded_apps(OldAppFiles, NewAppFiles), + + %% Get a list of any appup files that exist in the new release + NewAppUpFiles = rebar_utils:find_files( + filename:join([NewName, "lib"]), "^.*.appup$"), + + %% Convert the list of appup files into app names + AppUpApps = lists:map(fun(File) -> + file_to_name(File) + end, NewAppUpFiles), + + %% Create a list of apps that don't already have appups + Apps = genappup_which_apps(UpgradedApps, AppUpApps), + + %% Generate appup files + generate_appup_files(Name, OldVerPath, Apps), + + ok. + +%% =================================================================== +%% Internal functions +%% =================================================================== + +get_upgraded_apps(OldAppFiles, NewAppFiles) -> + OldAppsVer = [get_app_version(AppFile) || AppFile <- OldAppFiles], + NewAppsVer = [get_app_version(AppFile) || AppFile <- NewAppFiles], + UpgradedApps = lists:subtract(NewAppsVer, OldAppsVer), + lists:map( + fun({App, NewVer}) -> + {App, OldVer} = proplists:lookup(App, OldAppsVer), + {App, {OldVer, NewVer}} + end, + UpgradedApps). + +get_app_version(File) -> + case file:consult(File) of + {ok,[{application, Name,[_,{vsn,Ver}|_]}]} -> + {Name, Ver}; + _ -> + ?ABORT("Failed to parse ~s~n", [File]) + end. + +file_to_name(File) -> + filename:rootname(filename:basename(File)). + +genappup_which_apps(UpgradedApps, [First|Rest]) -> + List = proplists:delete(First, UpgradedApps), + genappup_which_apps(List, Rest); +genappup_which_apps(Apps, []) -> + Apps. + +generate_appup_files(Name, OldVerPath, [{App, {OldVer, NewVer}}|Rest]) -> + OldEbinDir = filename:join([".", OldVerPath, "lib", + atom_to_list(App) ++ "-" ++ OldVer, "ebin"]), + NewEbinDir = filename:join([".", Name, "lib", + atom_to_list(App) ++ "-" ++ NewVer, "ebin"]), + + {AddedFiles, DeletedFiles, ChangedFiles} = beam_lib:cmp_dirs(NewEbinDir, + OldEbinDir), + + Added = [generate_instruction(added, File) || File <- AddedFiles], + Deleted = [generate_instruction(deleted, File) || File <- DeletedFiles], + Changed = [generate_instruction(changed, 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(Name, OldVerPath, 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, {File, _}) -> + {ok, {Name, List}} = beam_lib:chunks(File, [attributes, exports]), + Behavior = get_behavior(List), + CodeChange = is_code_change(List), + generate_instruction_advanced(Name, Behavior, CodeChange). + +generate_instruction_advanced(Name, undefined, undefined) -> + %% Not a behavior or code change, assume purely functional + {load_module, Name}; +generate_instruction_advanced(Name, [supervisor], _) -> + %% Supervisor + {update, Name, supervisor}; +generate_instruction_advanced(Name, _, code_change) -> + %% Includes code_change export + {update, Name, {advanced, []}}; +generate_instruction_advanced(Name, _, _) -> + %% Anything else + {update, Name}. + +get_behavior(List) -> + Attributes = proplists:get_value(attributes, List), + Behavior = case proplists:get_value(behavior, Attributes) of + undefined -> + proplists:get_value(behaviour, Attributes); + Else -> + Else + end, + Behavior. + +is_code_change(List) -> + Exports = proplists:get_value(exports, List), + case proplists:is_defined(code_change, Exports) of + true -> + code_change; + false -> + undefined + end. diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index c8eccc4..dc7de9b 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -37,7 +37,11 @@ erl_to_mod/1, abort/2, escript_foldl/3, - find_executable/1]). + find_executable/1, + get_reltool_release_info/1, + get_rel_release_info/2, + get_previous_release_path/0, + prop_check/3]). -include("rebar.hrl"). @@ -151,6 +155,42 @@ find_executable(Name) -> "\"" ++ filename:nativename(Path) ++ "\"" 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 release name and version from a rel file +get_rel_release_info(Name, Path) -> + [RelFile] = filelib:wildcard(filename:join([Path, "releases", "*", + Name ++ ".rel"])), + [BinDir|_] = re:replace(RelFile, Name ++ "\\.rel", ""), + {ok, [{release, {Name1, Ver}, _, _}]} = + file:consult(filename:join([binary_to_list(BinDir), + Name ++ ".rel"])), + {Name1, Ver}. + +%% Get the previous release path from a global variable +get_previous_release_path() -> + case rebar_config:get_global(previous_release, false) of + false -> + ?ABORT("previous_release=PATH is required to " + "create upgrade package~n", []); + OldVerPath -> + OldVerPath + end. + +%% Helper function for checking values and aborting when needed +prop_check(true, _, _) -> true; +prop_check(false, Msg, Args) -> ?ABORT(Msg, Args). + %% ==================================================================== %% Internal functions %% ==================================================================== diff --git a/test/upgrade_project/README.md b/test/upgrade_project/README.md index cf753e8..4ab439b 100644 --- a/test/upgrade_project/README.md +++ b/test/upgrade_project/README.md @@ -21,6 +21,7 @@ rebar compile rebar generate + rebar generate-appups previous_release=dummy_0.1 rebar generate-upgrade previous_release=dummy_0.1 tar -zvtf rel/dummy_0.2.tar.gz diff --git a/test/upgrade_project/apps/dummy/ebin/dummy.appup b/test/upgrade_project/apps/dummy/ebin/dummy.appup deleted file mode 100644 index e77f66f..0000000 --- a/test/upgrade_project/apps/dummy/ebin/dummy.appup +++ /dev/null @@ -1,8 +0,0 @@ -{"0.2", - [{"0.1",[ - {update, dummy_server, {advanced, [foo]}} - ]}], - [{"0.1",[ - {update, dummy_server, {advanced, [foo]}} - ]}] -}. -- cgit v1.1 From c6da0b3ef668531ad31e33f52d865c4e36f47313 Mon Sep 17 00:00:00 2001 From: joewilliams Date: Wed, 16 Feb 2011 07:48:51 -0800 Subject: Fix generate-appups regression (atom vs list) --- src/rebar_appups.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rebar_appups.erl b/src/rebar_appups.erl index e7333fd..b3a730e 100644 --- a/src/rebar_appups.erl +++ b/src/rebar_appups.erl @@ -108,7 +108,7 @@ file_to_name(File) -> filename:rootname(filename:basename(File)). genappup_which_apps(UpgradedApps, [First|Rest]) -> - List = proplists:delete(First, UpgradedApps), + List = proplists:delete(list_to_atom(First), UpgradedApps), genappup_which_apps(List, Rest); genappup_which_apps(Apps, []) -> Apps. -- cgit v1.1 From 377c9e86d5f8e8cf24cc2b2feab54bda067f569b Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Wed, 16 Feb 2011 12:28:40 +0100 Subject: Add PropEr support --- src/rebar_eunit.erl | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl index 28aeaf1..aee487c 100644 --- a/src/rebar_eunit.erl +++ b/src/rebar_eunit.erl @@ -177,33 +177,40 @@ get_eunit_opts(Config) -> BaseOpts ++ rebar_config:get_list(Config, eunit_opts, []). eunit_config(Config) -> - EqcOpts = case is_quickcheck_avail() of - true -> - [{d, 'EQC'}]; - false -> - [] - end, + EqcOpts = eqc_opts(), + PropErOpts = proper_opts(), ErlOpts = rebar_config:get_list(Config, erl_opts, []), EunitOpts = rebar_config:get_list(Config, eunit_compile_opts, []), Opts = [{d, 'TEST'}, debug_info] ++ - ErlOpts ++ EunitOpts ++ EqcOpts, + ErlOpts ++ EunitOpts ++ EqcOpts ++ PropErOpts, Config1 = rebar_config:set(Config, erl_opts, Opts), FirstErls = rebar_config:get_list(Config1, eunit_first_files, []), rebar_config:set(Config1, erl_first_files, FirstErls). -is_quickcheck_avail() -> - case erlang:get(is_quickcheck_avail) of + +eqc_opts() -> + define_if('PROPER', is_lib_avail(is_eqc_avail, eqc, + "eqc.hrl", "QuickCheck")). +proper_opts() -> + define_if('EQC', is_lib_avail(is_proper_avail, proper, + "proper.hrl", "PropEr")). + +define_if(Def, true) -> [{d, Def}]; +define_if(_Def, false) -> []. + +is_lib_avail(DictKey, Mod, Hrl, Name) -> + case erlang:get(DictKey) of undefined -> - case code:lib_dir(eqc, include) of - {error, bad_name} -> - IsAvail = false; - Dir -> - IsAvail = filelib:is_regular(filename:join(Dir, "eqc.hrl")) - end, - erlang:put(is_quickcheck_avail, IsAvail), - ?DEBUG("Quickcheck availability: ~p\n", [IsAvail]), + IsAvail = case code:lib_dir(Mod, include) of + {error, bad_name} -> + false; + Dir -> + filelib:is_regular(filename:join(Dir, Hrl)) + end, + erlang:put(DictKey, IsAvail), + ?DEBUG("~s availability: ~p\n", [Name, IsAvail]), IsAvail; IsAvail -> IsAvail -- cgit v1.1 From 4e8dcfbfade08b48fe38bfe041459960b0ff74c3 Mon Sep 17 00:00:00 2001 From: joewilliams Date: Wed, 16 Feb 2011 09:46:40 -0800 Subject: Clean up rebar_appups and rebar_upgrade --- src/rebar_appups.erl | 22 +++++------- src/rebar_rel_utils.erl | 48 ++++++++++++++++++++++++- src/rebar_upgrade.erl | 96 +++++++++++++++++++------------------------------ src/rebar_utils.erl | 35 ------------------ 4 files changed, 92 insertions(+), 109 deletions(-) diff --git a/src/rebar_appups.erl b/src/rebar_appups.erl index b3a730e..dbc1561 100644 --- a/src/rebar_appups.erl +++ b/src/rebar_appups.erl @@ -40,13 +40,13 @@ 'generate-appups'(_Config, ReltoolFile) -> %% Get the old release path - OldVerPath = rebar_utils:get_previous_release_path(), + OldVerPath = rebar_rel_utils:get_previous_release_path(), %% Get the new and old release name and versions - {Name, _Ver} = rebar_utils:get_reltool_release_info(ReltoolFile), + {Name, _Ver} = rebar_rel_utils:get_reltool_release_info(ReltoolFile), NewVerPath = filename:join([".", Name]), - {NewName, NewVer} = rebar_utils:get_rel_release_info(Name, NewVerPath), - {OldName, OldVer} = rebar_utils:get_rel_release_info(Name, OldVerPath), + {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, @@ -86,8 +86,10 @@ %% =================================================================== get_upgraded_apps(OldAppFiles, NewAppFiles) -> - OldAppsVer = [get_app_version(AppFile) || AppFile <- OldAppFiles], - NewAppsVer = [get_app_version(AppFile) || AppFile <- NewAppFiles], + OldAppsVer = [{rebar_app_utils:app_name(AppFile), + rebar_app_utils:app_vsn(AppFile)} || AppFile <- OldAppFiles], + NewAppsVer = [{rebar_app_utils:app_name(AppFile), + rebar_app_utils:app_vsn(AppFile)} || AppFile <- NewAppFiles], UpgradedApps = lists:subtract(NewAppsVer, OldAppsVer), lists:map( fun({App, NewVer}) -> @@ -96,14 +98,6 @@ get_upgraded_apps(OldAppFiles, NewAppFiles) -> end, UpgradedApps). -get_app_version(File) -> - case file:consult(File) of - {ok,[{application, Name,[_,{vsn,Ver}|_]}]} -> - {Name, Ver}; - _ -> - ?ABORT("Failed to parse ~s~n", [File]) - end. - file_to_name(File) -> filename:rootname(filename:basename(File)). diff --git a/src/rebar_rel_utils.erl b/src/rebar_rel_utils.erl index 91031e8..94a10b0 100644 --- a/src/rebar_rel_utils.erl +++ b/src/rebar_rel_utils.erl @@ -26,7 +26,14 @@ %% ------------------------------------------------------------------- -module(rebar_rel_utils). --export([is_rel_dir/0, is_rel_dir/1]). +-export([is_rel_dir/0, + is_rel_dir/1, + get_reltool_release_info/1, + get_rel_release_info/1, + get_rel_release_info/2, + get_previous_release_path/0]). + +-include("rebar.hrl"). is_rel_dir() -> is_rel_dir(rebar_utils:get_cwd()). @@ -39,3 +46,42 @@ is_rel_dir(Dir) -> false -> false 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 release name and version from a rel file +get_rel_release_info(RelFile) -> + case file:consult(RelFile) of + {ok, [{release, {Name, Ver}, _, _}]} -> + {Name, Ver}; + _ -> + ?ABORT("Failed to parse ~s~n", [RelFile]) + end. + +%% Get release name and version from a name and a path +get_rel_release_info(Name, Path) -> + [RelFile] = filelib:wildcard(filename:join([Path, "releases", "*", + Name ++ ".rel"])), + [BinDir|_] = re:replace(RelFile, Name ++ "\\.rel", ""), + get_rel_release_info(filename:join([binary_to_list(BinDir), + Name ++ ".rel"])). + +%% Get the previous release path from a global variable +get_previous_release_path() -> + case rebar_config:get_global(previous_release, false) of + false -> + ?ABORT("previous_release=PATH is required to " + "create upgrade package~n", []); + OldVerPath -> + OldVerPath + end. diff --git a/src/rebar_upgrade.erl b/src/rebar_upgrade.erl index 639ddef..a1b34df 100644 --- a/src/rebar_upgrade.erl +++ b/src/rebar_upgrade.erl @@ -4,7 +4,7 @@ %% %% rebar: Erlang Build Tools %% -%% Copyright (c) 2011 Joe Williams +%% 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 @@ -32,91 +32,69 @@ -export(['generate-upgrade'/2]). -%% public api +%% ==================================================================== +%% Public API +%% ==================================================================== 'generate-upgrade'(_Config, ReltoolFile) -> - case rebar_config:get_global(previous_release, false) of - false -> - ?ABORT("previous_release=PATH is required to " - "create upgrade package~n", []); - OldVerPath -> - %% Run checks to make sure that building a package is possible - {NewName, NewVer} = run_checks(OldVerPath, ReltoolFile), - NameVer = NewName ++ "_" ++ NewVer, + %% Get the old release path + OldVerPath = rebar_rel_utils:get_previous_release_path(), + + %% Run checks to make sure that building a package is possible + {NewName, NewVer} = run_checks(OldVerPath, ReltoolFile), + NameVer = NewName ++ "_" ++ NewVer, - %% Save the code path prior to doing anything - OrigPath = code:get_path(), + %% 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), + %% Prepare the environment for building the package + ok = setup(OldVerPath, NewName, NewVer, NameVer), - %% Build the package - run_systools(NameVer, NewName), + %% Build the package + run_systools(NameVer, NewName), - %% Boot file changes - {ok, _} = boot_files(NewVer, NewName), + %% Boot file changes + {ok, _} = boot_files(NewVer, NewName), - %% Extract upgrade and tar it back up with changes - make_tar(NameVer), + %% Extract upgrade and tar it back up with changes + make_tar(NameVer), - %% Clean up files that systools created - ok = cleanup(NameVer, NewName, NewVer), + %% Clean up files that systools created + ok = cleanup(NameVer, NewName, NewVer), - %% Restore original path - true = code:set_path(OrigPath), + %% Restore original path + true = code:set_path(OrigPath), - ok - end. + ok. -%% internal api +%% =================================================================== +%% Internal functions +%% ================================================================== run_checks(OldVerPath, ReltoolFile) -> - true = prop_check(filelib:is_dir(OldVerPath), + true = rebar_utils:prop_check(filelib:is_dir(OldVerPath), "Release directory doesn't exist (~p)~n", [OldVerPath]), - {Name, Ver} = get_release_name(ReltoolFile), + {Name, Ver} = rebar_rel_utils:get_reltool_release_info(ReltoolFile), NamePath = filename:join([".", Name]), - true = prop_check(filelib:is_dir(NamePath), + true = rebar_utils:prop_check(filelib:is_dir(NamePath), "Release directory doesn't exist (~p)~n", [NamePath]), - {NewName, NewVer} = get_release_version(Name, NamePath), - {OldName, OldVer} = get_release_version(Name, OldVerPath), + {NewName, NewVer} = rebar_rel_utils:get_rel_release_info(Name, NamePath), + {OldName, OldVer} = rebar_rel_utils:get_rel_release_info(Name, OldVerPath), - true = prop_check(NewName == OldName, + true = rebar_utils:prop_check(NewName == OldName, "New and old .rel release names do not match~n", []), - true = prop_check(Name == NewName, + true = rebar_utils:prop_check(Name == NewName, "Reltool and .rel release names do not match~n", []), - true = prop_check(NewVer =/= OldVer, + true = rebar_utils:prop_check(NewVer =/= OldVer, "New and old .rel contain the same version~n", []), - true = prop_check(Ver == NewVer, + true = rebar_utils:prop_check(Ver == NewVer, "Reltool and .rel versions do not match~n", []), {NewName, NewVer}. -get_release_name(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_release_version(Name, Path) -> - [RelFile] = filelib:wildcard(filename:join([Path, "releases", "*", - Name ++ ".rel"])), - [BinDir|_] = re:replace(RelFile, Name ++ "\\.rel", ""), - {ok, [{release, {Name1, Ver}, _, _}]} = - file:consult(filename:join([binary_to_list(BinDir), - Name ++ ".rel"])), - {Name1, Ver}. - -prop_check(true, _, _) -> true; -prop_check(false, Msg, Args) -> ?ABORT(Msg, Args). - setup(OldVerPath, NewName, NewVer, NameVer) -> NewRelPath = filename:join([".", NewName]), Src = filename:join([NewRelPath, "releases", diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index dc7de9b..2822c0f 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -38,9 +38,6 @@ abort/2, escript_foldl/3, find_executable/1, - get_reltool_release_info/1, - get_rel_release_info/2, - get_previous_release_path/0, prop_check/3]). -include("rebar.hrl"). @@ -155,38 +152,6 @@ find_executable(Name) -> "\"" ++ filename:nativename(Path) ++ "\"" 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 release name and version from a rel file -get_rel_release_info(Name, Path) -> - [RelFile] = filelib:wildcard(filename:join([Path, "releases", "*", - Name ++ ".rel"])), - [BinDir|_] = re:replace(RelFile, Name ++ "\\.rel", ""), - {ok, [{release, {Name1, Ver}, _, _}]} = - file:consult(filename:join([binary_to_list(BinDir), - Name ++ ".rel"])), - {Name1, Ver}. - -%% Get the previous release path from a global variable -get_previous_release_path() -> - case rebar_config:get_global(previous_release, false) of - false -> - ?ABORT("previous_release=PATH is required to " - "create upgrade package~n", []); - OldVerPath -> - OldVerPath - end. - %% Helper function for checking values and aborting when needed prop_check(true, _, _) -> true; prop_check(false, Msg, Args) -> ?ABORT(Msg, Args). -- cgit v1.1 From 1e9b2b844b844a990269f68535f5bbf02ac522b3 Mon Sep 17 00:00:00 2001 From: joewilliams Date: Thu, 17 Feb 2011 10:12:32 -0800 Subject: Clean up trailing whitespace --- src/rebar_appups.erl | 4 ++-- src/rebar_rel_utils.erl | 4 ++-- src/rebar_upgrade.erl | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rebar_appups.erl b/src/rebar_appups.erl index dbc1561..ab5af29 100644 --- a/src/rebar_appups.erl +++ b/src/rebar_appups.erl @@ -86,9 +86,9 @@ %% =================================================================== get_upgraded_apps(OldAppFiles, NewAppFiles) -> - OldAppsVer = [{rebar_app_utils:app_name(AppFile), + OldAppsVer = [{rebar_app_utils:app_name(AppFile), rebar_app_utils:app_vsn(AppFile)} || AppFile <- OldAppFiles], - NewAppsVer = [{rebar_app_utils:app_name(AppFile), + NewAppsVer = [{rebar_app_utils:app_name(AppFile), rebar_app_utils:app_vsn(AppFile)} || AppFile <- NewAppFiles], UpgradedApps = lists:subtract(NewAppsVer, OldAppsVer), lists:map( diff --git a/src/rebar_rel_utils.erl b/src/rebar_rel_utils.erl index 94a10b0..9729e20 100644 --- a/src/rebar_rel_utils.erl +++ b/src/rebar_rel_utils.erl @@ -26,7 +26,7 @@ %% ------------------------------------------------------------------- -module(rebar_rel_utils). --export([is_rel_dir/0, +-export([is_rel_dir/0, is_rel_dir/1, get_reltool_release_info/1, get_rel_release_info/1, @@ -73,7 +73,7 @@ get_rel_release_info(Name, Path) -> [RelFile] = filelib:wildcard(filename:join([Path, "releases", "*", Name ++ ".rel"])), [BinDir|_] = re:replace(RelFile, Name ++ "\\.rel", ""), - get_rel_release_info(filename:join([binary_to_list(BinDir), + get_rel_release_info(filename:join([binary_to_list(BinDir), Name ++ ".rel"])). %% Get the previous release path from a global variable diff --git a/src/rebar_upgrade.erl b/src/rebar_upgrade.erl index a1b34df..39b2c61 100644 --- a/src/rebar_upgrade.erl +++ b/src/rebar_upgrade.erl @@ -39,7 +39,7 @@ 'generate-upgrade'(_Config, ReltoolFile) -> %% Get the old release path OldVerPath = rebar_rel_utils:get_previous_release_path(), - + %% Run checks to make sure that building a package is possible {NewName, NewVer} = run_checks(OldVerPath, ReltoolFile), NameVer = NewName ++ "_" ++ NewVer, -- cgit v1.1 From 0a06a53c8e60723f547b7abfc23bdc637035c307 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Thu, 17 Feb 2011 18:58:32 +0100 Subject: Add Anders 'andekar' to THANKS file --- THANKS | 1 + 1 file changed, 1 insertion(+) diff --git a/THANKS b/THANKS index 0e40965..e20f433 100644 --- a/THANKS +++ b/THANKS @@ -42,3 +42,4 @@ Daniel Reverri Jesper Louis Andersen Richard Jones Tim Watson +Anders 'andekar' -- cgit v1.1 From b0860da1241e482e5125714e1cd343c9d734db10 Mon Sep 17 00:00:00 2001 From: Adam Kocoloski Date: Thu, 2 Dec 2010 17:12:54 -0500 Subject: Expand {vsn,git} in app.src to git-describe output --- src/rebar_app_utils.erl | 9 ++++++++- src/rebar_otp_app.erl | 7 ++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl index 1fa870b..34d357a 100644 --- a/src/rebar_app_utils.erl +++ b/src/rebar_app_utils.erl @@ -89,7 +89,14 @@ app_applications(AppFile) -> app_vsn(AppFile) -> case load_app_file(AppFile) of {ok, _, AppInfo} -> - get_value(vsn, AppInfo, AppFile); + case get_value(vsn, AppInfo, AppFile) of + git -> + Cmd = "git describe --tags --always", + {ok, VsnString} = rebar_utils:sh(Cmd, []), + string:strip(VsnString, right, $\n); + Version -> + Version + end; {error, Reason} -> ?ABORT("Failed to extract vsn from ~s: ~p\n", [AppFile, Reason]) diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl index 4f21a67..f92de5c 100644 --- a/src/rebar_otp_app.erl +++ b/src/rebar_otp_app.erl @@ -96,8 +96,13 @@ preprocess(Config, AppSrcFile) -> AppVars = load_app_vars(Config) ++ [{modules, ebin_modules()}], A1 = apply_app_vars(AppVars, AppData), + + %% AppSrcFile may contain instructions for generating a vsn number + Vsn = rebar_app_utils:app_vsn(AppSrcFile), + A2 = lists:keystore(vsn, 1, A1, {vsn, Vsn}), + %% Build the final spec as a string - Spec = io_lib:format("~p.\n", [{application, AppName, A1}]), + Spec = io_lib:format("~p.\n", [{application, AppName, A2}]), %% Setup file .app filename and write new contents AppFile = rebar_app_utils:app_src_to_app(AppSrcFile), -- cgit v1.1 From 01a7473dac44befe05c460e28c601e2eec785b41 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Wed, 16 Feb 2011 23:47:23 +0100 Subject: Add {vsn,Vcs} support for bzr, hg and svn --- src/rebar_app_utils.erl | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl index 34d357a..f50ac86 100644 --- a/src/rebar_app_utils.erl +++ b/src/rebar_app_utils.erl @@ -90,12 +90,11 @@ app_vsn(AppFile) -> case load_app_file(AppFile) of {ok, _, AppInfo} -> case get_value(vsn, AppInfo, AppFile) of - git -> - Cmd = "git describe --tags --always", - {ok, VsnString} = rebar_utils:sh(Cmd, []), - string:strip(VsnString, right, $\n); - Version -> - Version + git -> vcs_vsn(git); + hg -> vcs_vsn(hg); + bzr -> vcs_vsn(bzr); + svn -> vcs_vsn(svn); + Version -> Version end; {error, Reason} -> ?ABORT("Failed to extract vsn from ~s: ~p\n", @@ -131,3 +130,13 @@ get_value(Key, AppInfo, AppFile) -> Value -> Value end. + +vcs_vsn(Vcs) -> + Cmd = vcs_vsn_cmd(Vcs), + {ok, VsnString} = rebar_utils:sh(Cmd, [{use_stdout, false}]), + string:strip(VsnString, right, $\n). + +vcs_vsn_cmd(git) -> "git describe --always --tags"; +vcs_vsn_cmd(hg) -> "hg identify -i"; +vcs_vsn_cmd(bzr) -> "bzr revno"; +vcs_vsn_cmd(svn) -> "svnversion". -- cgit v1.1 From 6056c63eed288736c912c82d6f36aa7dd055f9ca Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Fri, 18 Feb 2011 10:59:57 +0100 Subject: Clean up and simplify {vsn, VCS} support --- src/rebar_app_utils.erl | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl index f50ac86..27b9176 100644 --- a/src/rebar_app_utils.erl +++ b/src/rebar_app_utils.erl @@ -89,13 +89,7 @@ app_applications(AppFile) -> app_vsn(AppFile) -> case load_app_file(AppFile) of {ok, _, AppInfo} -> - case get_value(vsn, AppInfo, AppFile) of - git -> vcs_vsn(git); - hg -> vcs_vsn(hg); - bzr -> vcs_vsn(bzr); - svn -> vcs_vsn(svn); - Version -> Version - end; + vcs_vsn(get_value(vsn, AppInfo, AppFile)); {error, Reason} -> ?ABORT("Failed to extract vsn from ~s: ~p\n", [AppFile, Reason]) @@ -132,11 +126,16 @@ get_value(Key, AppInfo, AppFile) -> end. vcs_vsn(Vcs) -> - Cmd = vcs_vsn_cmd(Vcs), - {ok, VsnString} = rebar_utils:sh(Cmd, [{use_stdout, false}]), - string:strip(VsnString, right, $\n). + case vcs_vsn_cmd(Vcs) of + {unknown, VsnString} -> + VsnString; + Cmd -> + {ok, VsnString} = rebar_utils:sh(Cmd, [{use_stdout, false}]), + string:strip(VsnString, right, $\n) + end. vcs_vsn_cmd(git) -> "git describe --always --tags"; -vcs_vsn_cmd(hg) -> "hg identify -i"; +vcs_vsn_cmd(hg) -> "hg identify -i"; vcs_vsn_cmd(bzr) -> "bzr revno"; -vcs_vsn_cmd(svn) -> "svnversion". +vcs_vsn_cmd(svn) -> "svnversion"; +vcs_vsn_cmd(Version) -> {unknown, Version}. -- cgit v1.1