diff options
37 files changed, 780 insertions, 120 deletions
diff --git a/dialyzer_reference b/dialyzer_reference index a50bb88..fccada2 100644 --- a/dialyzer_reference +++ b/dialyzer_reference @@ -1,3 +1,3 @@ -rebar_eunit.erl:351: Call to missing or unexported function eunit_test:function_wrapper/2 +rebar_eunit.erl:388: Call to missing or unexported function eunit_test:function_wrapper/2 rebar_utils.erl:162: Call to missing or unexported function escript:foldl/3 diff --git a/inttest/tdeps1/a.rebar.config b/inttest/tdeps1/a.rebar.config index 01609ee..991ea5a 100644 --- a/inttest/tdeps1/a.rebar.config +++ b/inttest/tdeps1/a.rebar.config @@ -1 +1 @@ -{deps, [{b, "1", {hg, "../repo/b", "tip"}}]}. +{deps, [{b, "1", {git, "../repo/b"}}]}. diff --git a/inttest/tdeps1/b.rebar.config b/inttest/tdeps1/b.rebar.config index 59c8987..ffbd0db 100644 --- a/inttest/tdeps1/b.rebar.config +++ b/inttest/tdeps1/b.rebar.config @@ -1 +1 @@ -{deps, [{c, "1", {hg, "../repo/c", "tip"}}]}. +{deps, [{c, "1", {git, "../repo/c"}}]}. diff --git a/inttest/tdeps1/tdeps1_rt.erl b/inttest/tdeps1/tdeps1_rt.erl index 43184c6..9f21c81 100644 --- a/inttest/tdeps1/tdeps1_rt.erl +++ b/inttest/tdeps1/tdeps1_rt.erl @@ -24,11 +24,11 @@ files() -> ]. run(_Dir) -> - %% Initialize the b/c apps as mercurial repos so that dependencies pull + %% Initialize the b/c apps as git repos so that dependencies pull %% properly - HgCmd = "/bin/sh -c \"hg init && hg add && hg commit -m 'Initial commit'\"", - {ok, _} = retest_sh:run(HgCmd, [{dir, "repo/b"}]), - {ok, _} = retest_sh:run(HgCmd, [{dir, "repo/c"}]), + GitCmd = "/bin/sh -c \"git init && git add -A && git commit -a -m 'Initial commit'\"", + {ok, _} = retest_sh:run(GitCmd, [{dir, "repo/b"}]), + {ok, _} = retest_sh:run(GitCmd, [{dir, "repo/c"}]), {ok, _} = retest_sh:run("./rebar get-deps compile", []), diff --git a/inttest/tdeps2/a.rebar.config b/inttest/tdeps2/a.rebar.config index 01609ee..991ea5a 100644 --- a/inttest/tdeps2/a.rebar.config +++ b/inttest/tdeps2/a.rebar.config @@ -1 +1 @@ -{deps, [{b, "1", {hg, "../repo/b", "tip"}}]}. +{deps, [{b, "1", {git, "../repo/b"}}]}. diff --git a/inttest/tdeps2/b.rebar.config b/inttest/tdeps2/b.rebar.config index 59c8987..ffbd0db 100644 --- a/inttest/tdeps2/b.rebar.config +++ b/inttest/tdeps2/b.rebar.config @@ -1 +1 @@ -{deps, [{c, "1", {hg, "../repo/c", "tip"}}]}. +{deps, [{c, "1", {git, "../repo/c"}}]}. diff --git a/inttest/tdeps2/tdeps2_rt.erl b/inttest/tdeps2/tdeps2_rt.erl index bad546e..dca5f03 100644 --- a/inttest/tdeps2/tdeps2_rt.erl +++ b/inttest/tdeps2/tdeps2_rt.erl @@ -34,9 +34,9 @@ files() -> 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'\"", - {ok, _} = retest_sh:run(HgCmd, [{dir, "repo/b"}]), - {ok, _} = retest_sh:run(HgCmd, [{dir, "repo/c"}]), + GitCmd = "/bin/sh -c \"git init && git add -A && git commit -a -m 'Initial commit'\"", + {ok, _} = retest_sh:run(GitCmd, [{dir, "repo/b"}]), + {ok, _} = retest_sh:run(GitCmd, [{dir, "repo/c"}]), {ok, _} = retest_sh:run("./rebar -v get-deps compile", []), ok. diff --git a/priv/templates/simplenode.erl.script b/priv/templates/simplenode.erl.script index 6f65e3f..7919d69 100644 --- a/priv/templates/simplenode.erl.script +++ b/priv/templates/simplenode.erl.script @@ -1,13 +1,23 @@ #!/bin/sh -## 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). +# /bin/sh on Solaris is not a POSIX compatible shell, but /usr/bin/ksh is. +if [ `uname -s` = 'SunOS' -a "${POSIX_SHELL}" != "true" ]; then + POSIX_SHELL="true" + export POSIX_SHELL + exec /usr/bin/ksh $0 "$@" +fi + +# clear it so if we invoke other scripts, they run as ksh as well +unset POSIX_SHELL + +## 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. +## 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) diff --git a/priv/templates/simplenode.nodetool b/priv/templates/simplenode.nodetool index eb08fa4..54ee6d6 100644..100755 --- a/priv/templates/simplenode.nodetool +++ b/priv/templates/simplenode.nodetool @@ -1,3 +1,4 @@ +#!/usr/bin/env escript %% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ft=erlang ts=4 sw=4 et %% ------------------------------------------------------------------- @@ -5,25 +6,53 @@ %% nodetool: Helper Script for interacting with live nodes %% %% ------------------------------------------------------------------- +-mode(compile). main(Args) -> ok = start_epmd(), %% Extract the args {RestArgs, TargetNode} = process_args(Args, [], undefined), + %% any commands that don't need a running node + case RestArgs of + ["chkconfig", File] -> + case file:consult(File) of + {ok, _} -> + io:format("ok\n"), + halt(0); + {error, {Line, Mod, Term}} -> + io:format(standard_error, ["Error on line ", + file:format_error({Line, Mod, Term}), "\n"], []), + halt(1); + {error, R} -> + io:format(standard_error, ["Error reading config file: ", + file:format_error(R), "\n"], []), + halt(1) + end; + _ -> + ok + end, + %% 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 + case {net_kernel:hidden_connect_node(TargetNode), + net_adm:ping(TargetNode)} of {true, pong} -> ok; + {false,pong} -> + io:format("Failed to connect to node ~p .\n", [TargetNode]), + halt(1); {_, pang} -> io:format("Node ~p not responding to pings.\n", [TargetNode]), halt(1) end, case RestArgs of + ["getpid"] -> + io:format("~p\n", + [list_to_integer(rpc:call(TargetNode, os, getpid, []))]); ["ping"] -> - %% If we got this far, the node already responsed to a ping, so just dump - %% a "pong" + %% 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)]); @@ -32,7 +61,9 @@ 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), + case rpc:call(TargetNode, + list_to_atom(Module), + list_to_atom(Function), [RpcArgs], 60000) of ok -> ok; @@ -42,8 +73,23 @@ main(Args) -> _ -> halt(1) end; + ["rpc_infinity", Module, Function | RpcArgs] -> + case rpc:call(TargetNode, + list_to_atom(Module), + list_to_atom(Function), + [RpcArgs], infinity) 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), + 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]), @@ -53,7 +99,7 @@ main(Args) -> end; Other -> io:format("Other: ~p\n", [Other]), - io:format("Usage: nodetool {ping|stop|restart|reboot}\n") + io:format("Usage: nodetool {chkconfig|getpid|ping|stop|restart|reboot|rpc|rpc_infinity|rpcterms}\n") end, net_kernel:stop(). diff --git a/priv/templates/simplenode.reltool.config b/priv/templates/simplenode.reltool.config index b580c2a..4189329 100644 --- a/priv/templates/simplenode.reltool.config +++ b/priv/templates/simplenode.reltool.config @@ -1,3 +1,5 @@ +%% -*- mode: erlang -*- +%% ex: ft=erlang {sys, [ {lib_dirs, []}, {erts, [{mod_cond, derived}, {app_file, strip}]}, diff --git a/priv/templates/simplenode.runner b/priv/templates/simplenode.runner index 43d90bc..9835d92 100755 --- a/priv/templates/simplenode.runner +++ b/priv/templates/simplenode.runner @@ -2,6 +2,19 @@ # -*- tab-width:4;indent-tabs-mode:nil -*- # ex: ts=4 sw=4 et +# /bin/sh on Solaris is not a POSIX compatible shell, but /usr/bin/ksh is. +if [ `uname -s` = 'SunOS' -a "${POSIX_SHELL}" != "true" ]; then + POSIX_SHELL="true" + export POSIX_SHELL + # To support 'whoami' add /usr/ucb to path + PATH=/usr/ucb:$PATH + export PATH + exec /usr/bin/ksh $0 "$@" +fi + +# clear it so if we invoke other scripts, they run as ksh +unset POSIX_SHELL + RUNNER_SCRIPT_DIR=$(cd ${0%/*} && pwd) CALLER_DIR=$PWD @@ -11,10 +24,17 @@ RUNNER_ETC_DIR=$RUNNER_BASE_DIR/etc # Note the trailing slash on $PIPE_DIR/ PIPE_DIR=/tmp/$RUNNER_BASE_DIR/ RUNNER_USER= +WHOAMI=$(whoami) # 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 $@ +if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then + type sudo > /dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "sudo doesn't appear to be installed and your EUID isn't $RUNNER_USER" 1>&2 + exit 1 + fi + echo "Attempting to restart script through sudo -H -u $RUNNER_USER" >&2 + exec sudo -H -u $RUNNER_USER -i $RUNNER_SCRIPT_DIR/$RUNNER_SCRIPT $@ fi # Identify the script name @@ -25,7 +45,8 @@ START_ERL=`cat $RUNNER_BASE_DIR/releases/start_erl.data` ERTS_VSN=${START_ERL% *} APP_VSN=${START_ERL#* } -# Use $CWD/vm.args if exists, otherwise releases/APP_VSN/vm.args, or else etc/vm.args +# Use $CWD/vm.args if exists, otherwise releases/APP_VSN/vm.args, or +# else etc/vm.args if [ -e "$CALLER_DIR/vm.args" ]; then VMARGS_PATH=$CALLER_DIR/vm.args USE_DIR=$CALLER_DIR @@ -54,7 +75,7 @@ else fi # Extract the target node name from node.args -NAME_ARG=`egrep '^-s?name' $VMARGS_PATH` +NAME_ARG=`egrep '^\-s?name' $VMARGS_PATH` if [ -z "$NAME_ARG" ]; then echo "vm.args needs to have either -name or -sname parameter." exit 1 @@ -64,12 +85,13 @@ fi REMSH_TYPE=`echo $NAME_ARG | awk '{print $1}'` REMSH_NAME=`echo $NAME_ARG | awk '{print $2}'` -# Note the `date +%s`, used to allow multiple remsh to the same node transparently +# Note the `date +%s`, used to allow multiple remsh to the same node +# transparently REMSH_NAME_ARG="$REMSH_TYPE remsh`date +%s`@`echo $REMSH_NAME | awk -F@ '{print $2}'`" REMSH_REMSH_ARG="-remsh $REMSH_NAME" # Extract the target cookie -COOKIE_ARG=`grep '^-setcookie' $VMARGS_PATH` +COOKIE_ARG=`grep '^\-setcookie' $VMARGS_PATH` if [ -z "$COOKIE_ARG" ]; then echo "vm.args needs to have a -setcookie parameter." exit 1 @@ -81,7 +103,6 @@ cd $USE_DIR # Make sure log directory exists mkdir -p $USE_DIR/log - # Add ERTS bin dir to our path ERTS_PATH=$RUNNER_BASE_DIR/erts-$ERTS_VSN/bin @@ -91,11 +112,35 @@ NODETOOL="$ERTS_PATH/escript $ERTS_PATH/nodetool $NAME_ARG $COOKIE_ARG" # Setup remote shell command to control node REMSH="$ERTS_PATH/erl $REMSH_NAME_ARG $REMSH_REMSH_ARG $COOKIE_ARG" +# Common functions + +# Ping node without allowing nodetool to take stdin +ping_node() { + $NODETOOL ping < /dev/null +} + +# Set the PID global variable, return 1 on error +get_pid() { + PID=`$NODETOOL getpid < /dev/null` + ES=$? + if [ "$ES" -ne 0 ]; then + echo "Node is not running!" + return 1 + fi + + # don't allow empty or init pid's + if [ -z $PID ] || [ "$PID" -le 1 ]; then + return 1 + fi + + return 0 +} + # Check the first argument for instructions case "$1" in start|start_boot) # Make sure there is not already a node running - RES=`$NODETOOL ping` + RES=`ping_node` if [ "$RES" = "pong" ]; then echo "Node is already running!" exit 1 @@ -122,27 +167,28 @@ case "$1" in 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}'` - ;; + Darwin) + # Make sure we explicitly set this because iTerm.app doesn't for + # some reason. + COMMAND_MODE=unix2003 esac + + # Get the PID from nodetool + get_pid + GPR=$? + if [ "$GPR" -ne 0 ] || [ -z $PID ]; then + exit $GPR + fi + + # Tell nodetool to initiate a stop $NODETOOL stop ES=$? if [ "$ES" -ne 0 ]; then exit $ES fi - while `kill -0 $PID 2>/dev/null`; + + # Wait for the node to completely stop... + while `kill -s 0 $PID 2>/dev/null` do sleep 1 done @@ -168,7 +214,7 @@ case "$1" in ping) ## See if the VM is alive - $NODETOOL ping + ping_node ES=$? if [ "$ES" -ne 0 ]; then exit $ES @@ -176,8 +222,8 @@ case "$1" in ;; attach) - # Make sure a node IS running - RES=`$NODETOOL ping` + # Make sure a node is running + ping_node ES=$? if [ "$ES" -ne 0 ]; then echo "Node is not running!" @@ -189,8 +235,8 @@ case "$1" in ;; remote_console) - # Make sure a node IS running - RES=`$NODETOOL ping` + # Make sure a node is running + ping_node ES=$? if [ "$ES" -ne 0 ]; then echo "Node is not running!" @@ -210,7 +256,7 @@ case "$1" in fi # Make sure a node IS running - RES=`$NODETOOL ping` + ping_node ES=$? if [ "$ES" -ne 0 ]; then echo "Node is not running!" @@ -283,8 +329,17 @@ case "$1" in # Start the VM exec $CMD -- ${1+"$@"} ;; + getpid) + # Get the PID from nodetool + get_pid + ES=$? + if [ "$ES" -ne 0 ] || [ -z $PID ]; then + exit $ES + fi + echo $PID + ;; *) - echo "Usage: $SCRIPT {start|start_boot <file>|foreground|stop|restart|reboot|ping|console|console_clean|console_boot <file>|attach|remote_console|upgrade}" + echo "Usage: $SCRIPT {start|start_boot <file>|foreground|stop|restart|reboot|ping|console|getpid|console_clean|console_boot <file>|attach|remote_console|upgrade}" exit 1 ;; esac diff --git a/rebar.config.sample b/rebar.config.sample index a6fb03f..d8d61fc 100644 --- a/rebar.config.sample +++ b/rebar.config.sample @@ -156,7 +156,7 @@ {deps, [application_name, {application_name, "1.0.*"}, {application_name, "1.0.*", - {git, "git://github.com/basho/rebar.git", {branch, "master"}}}, + {git, "git://github.com/rebar/rebar.git", {branch, "master"}}}, %% Dependencies can be marked as 'raw'. Rebar does not require %% such dependencies to have a standard Erlang/OTP layout %% which assumes the presence of either @@ -171,7 +171,7 @@ %% 'raw' subdirectories: get-deps, update-deps, check-deps, %% list-deps and delete-deps. {application_name, "", - {git, "git://github.com/basho/rebar.git", {branch, "master"}}, + {git, "git://github.com/rebar/rebar.git", {branch, "master"}}, [raw]}]}. %% == Subdirectories == @@ -213,9 +213,9 @@ %% Optional custom xref queries (xref manual has details) specified as %% {xref_queries, [{query_string(), expected_query_result()},...]} -%% The following for example removes all references to ejabberd:*_msg/4 +%% The following for example removes all references to mod:*foo/4 %% functions from undefined external function calls as those are in a %% generated module {xref_queries, [{"(XC - UC) || (XU - X - B" - " - (\"ejabberd_logger\":\".*_msg\"/\"4\"))",[]}]}. + " - (\"mod\":\".*foo\"/\"4\"))",[]}]}. diff --git a/src/rebar.erl b/src/rebar.erl index c872ade..ded5ebe 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -76,8 +76,18 @@ run(BaseConfig, Commands) -> %% Internal functions %% ==================================================================== +run(["help"|RawCmds]) when RawCmds =/= [] -> + ok = load_rebar_app(), + Cmds = unabbreviate_command_names(RawCmds), + Args = parse_args(Cmds), + BaseConfig = init_config(Args), + {BaseConfig1, _} = save_options(BaseConfig, Args), + BaseConfig2 = init_config1(BaseConfig1), + rebar_core:help(BaseConfig2, [list_to_atom(C) || C <- Cmds]); run(["help"]) -> help(); +run(["info"|_]) -> + help(); run(["version"]) -> ok = load_rebar_app(), %% Display vsn and build time info @@ -138,6 +148,16 @@ init_config({Options, _NonOptArgs}) -> %% Initialize vsn cache rebar_config:set_xconf(BaseConfig1, vsn_cache, dict:new()). +init_config1(BaseConfig) -> + %% Determine the location of the rebar executable; important for pulling + %% resources out of the escript + ScriptName = filename:absname(escript:script_name()), + BaseConfig1 = rebar_config:set_xconf(BaseConfig, escript, ScriptName), + ?DEBUG("Rebar location: ~p\n", [ScriptName]), + %% Note the top-level directory for reference + AbsCwd = filename:absname(rebar_utils:get_cwd()), + rebar_config:set_xconf(BaseConfig1, base_dir, AbsCwd). + run_aux(BaseConfig, Commands) -> %% Make sure crypto is running case crypto:start() of @@ -148,18 +168,10 @@ run_aux(BaseConfig, Commands) -> %% 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 - ScriptName = filename:absname(escript:script_name()), - BaseConfig1 = rebar_config:set_xconf(BaseConfig, escript, ScriptName), - ?DEBUG("Rebar location: ~p\n", [ScriptName]), - - %% Note the top-level directory for reference - AbsCwd = filename:absname(rebar_utils:get_cwd()), - BaseConfig2 = rebar_config:set_xconf(BaseConfig1, base_dir, AbsCwd), + BaseConfig1 = init_config1(BaseConfig), %% Process each command, resetting any state between each one - rebar_core:process_commands(CommandAtoms, BaseConfig2). + rebar_core:process_commands(CommandAtoms, BaseConfig1). %% %% print help/usage string @@ -169,7 +181,29 @@ help() -> getopt:usage(OptSpecList, "rebar", "[var=value,...] <command,...>", [{"var=value", "rebar global variables (e.g. force=1)"}, - {"command", "Command to run (e.g. compile)"}]). + {"command", "Command to run (e.g. compile)"}]), + ?CONSOLE( + "Core rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n", + [ + {lib_dirs, []}, + {sub_dirs, ["dir1", "dir2"]}, + {plugins, [plugin1, plugin2]}, + {plugin_dir, "some_other_directory"}, + {pre_hooks, [{clean, "./prepare_package_files.sh"}, + {"linux", compile, "c_src/build_linux.sh"}, + {compile, "escript generate_headers"}, + {compile, "escript check_headers"}]}, + {post_hooks, [{clean, "touch file1.out"}, + {"freebsd", compile, "c_src/freebsd_tweaks.sh"}, + {eunit, "touch file2.out"}, + {compile, "touch postcompile.out"}]} + ]). %% %% Parse command line arguments using getopt and also filtering out any diff --git a/src/rebar_abnfc_compiler.erl b/src/rebar_abnfc_compiler.erl index 0e6749a..37731b5 100644 --- a/src/rebar_abnfc_compiler.erl +++ b/src/rebar_abnfc_compiler.erl @@ -47,6 +47,9 @@ -export([compile/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -62,11 +65,23 @@ compile(Config, _AppFile) -> option(module_ext, DtlOpts) ++ ".erl", fun compile_abnfc/3). - %% =================================================================== %% Internal functions %% =================================================================== +info(help, compile) -> + ?CONSOLE( + "Build ABNF (*.abnf) sources.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n", + [ + {abnfc_opts, [{doc_root, "src"}, + {out_dir, "src"}, + {source_ext, ".abnfc"}, + {module_ext, ""}]} + ]). + abnfc_opts(Config) -> rebar_config:get(Config, abnfc_opts, []). diff --git a/src/rebar_appups.erl b/src/rebar_appups.erl index 0aeccb6..722f161 100644 --- a/src/rebar_appups.erl +++ b/src/rebar_appups.erl @@ -31,6 +31,9 @@ -export(['generate-appups'/2]). +%% for internal use only +-export([info/2]). + -define(APPUPFILEFORMAT, "%% appup generated for ~p by rebar (~p)~n" "{~p, [{~p, ~p}], [{~p, []}]}.~n"). @@ -82,6 +85,13 @@ %% Internal functions %% =================================================================== +info(help, 'generate-appups') -> + ?CONSOLE("Generate appup files.~n" + "~n" + "Valid command line options:~n" + " previous_release=path~n", + []). + get_apps(Name, OldVerPath, NewVerPath) -> OldApps = rebar_rel_utils:get_rel_apps(Name, OldVerPath), ?DEBUG("Old Version Apps: ~p~n", [OldApps]), diff --git a/src/rebar_asn1_compiler.erl b/src/rebar_asn1_compiler.erl index d93a2e8..25e3fd3 100644 --- a/src/rebar_asn1_compiler.erl +++ b/src/rebar_asn1_compiler.erl @@ -30,6 +30,9 @@ -export([compile/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -48,6 +51,23 @@ clean(_Config, _AppFile) -> ok = rebar_file_utils:delete_each(GeneratedFiles), ok. +%% =================================================================== +%% Internal functions +%% =================================================================== + +info(help, compile) -> + info_help("Build ASN.1 (*.asn1) sources"); +info(help, clean) -> + info_help("Delete ASN.1 (*.asn1) results"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " {asn1_opts, []} (see asn1ct:compile/2 documentation)~n", + [Description]). + -spec compile_asn1(file:filename(), file:filename(), rebar_config:config()) -> ok. compile_asn1(Source, Target, Config) -> diff --git a/src/rebar_cleaner.erl b/src/rebar_cleaner.erl index 9ddeb8a..7a762f5 100644 --- a/src/rebar_cleaner.erl +++ b/src/rebar_cleaner.erl @@ -28,6 +28,9 @@ -export([clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -37,3 +40,17 @@ clean(Config, _AppFile) -> %% Get a list of files to delete from config and remove them FilesToClean = rebar_config:get(Config, clean_files, []), lists:foreach(fun (F) -> rebar_file_utils:rm_rf(F) end, FilesToClean). + +%% =================================================================== +%% Internal functions +%% =================================================================== + +info(help, clean) -> + ?CONSOLE( + "Delete list of files.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n", + [ + {clean_files, ["file", "file2"]} + ]). diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 5396dd5..36923a5 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -26,7 +26,7 @@ %% ------------------------------------------------------------------- -module(rebar_core). --export([process_commands/2]). +-export([process_commands/2, help/2]). -include("rebar.hrl"). @@ -34,6 +34,35 @@ %% Internal functions %% =================================================================== +help(ParentConfig, Commands) -> + %% get all core modules + {ok, AnyDirModules} = application:get_env(rebar, any_dir_modules), + {ok, RawCoreModules} = application:get_env(rebar, modules), + AppDirModules = proplists:get_value(app_dir, RawCoreModules), + RelDirModules = proplists:get_value(rel_dir, RawCoreModules), + CoreModules = AnyDirModules ++ AppDirModules ++ RelDirModules, + + %% get plugin modules + Predirs = [], + Dir = rebar_utils:get_cwd(), + PredirsAssoc = remember_cwd_predirs(Dir, Predirs), + Config = maybe_load_local_config(Dir, ParentConfig), + {ok, PluginModules} = plugin_modules(Config, PredirsAssoc), + + AllModules = CoreModules ++ PluginModules, + + lists:foreach( + fun(Cmd) -> + ?CONSOLE("==> help ~p~n~n", [Cmd]), + CmdModules = select_modules(AllModules, Cmd, []), + Modules = select_modules(CmdModules, info, []), + lists:foreach(fun(M) -> + ?CONSOLE("=== ~p:~p ===~n", [M, Cmd]), + M:info(help, Cmd), + ?CONSOLE("~n", []) + end, Modules) + end, Commands). + process_commands([], ParentConfig) -> AbortTrapped = rebar_config:get_xconf(ParentConfig, abort_trapped, false), case {get_operations(ParentConfig), AbortTrapped} of @@ -110,21 +139,21 @@ process_dir(Dir, ParentConfig, Command, DirSet) -> {ok, AvailModuleSets} = application:get_env(rebar, modules), ModuleSet = choose_module_set(AvailModuleSets, Dir), skip_or_process_dir(ModuleSet, Config, CurrentCodePath, - Dir, Command, DirSet) + Dir, Command, DirSet) end. skip_or_process_dir({[], undefined}=ModuleSet, Config, CurrentCodePath, - Dir, Command, DirSet) -> + Dir, Command, DirSet) -> process_dir1(Dir, Command, DirSet, Config, CurrentCodePath, ModuleSet); skip_or_process_dir({_, ModuleSetFile}=ModuleSet, Config, CurrentCodePath, - Dir, Command, DirSet) -> + Dir, Command, DirSet) -> case lists:suffix(".app.src", ModuleSetFile) orelse lists:suffix(".app", ModuleSetFile) of true -> %% .app or .app.src file, check if is_skipped_app skip_or_process_dir1(ModuleSetFile, ModuleSet, - Config, CurrentCodePath, Dir, - Command, DirSet); + Config, CurrentCodePath, Dir, + Command, DirSet); false -> %% not an app dir, no need to consider apps=/skip_apps= process_dir1(Dir, Command, DirSet, Config, @@ -132,7 +161,7 @@ skip_or_process_dir({_, ModuleSetFile}=ModuleSet, Config, CurrentCodePath, end. skip_or_process_dir1(AppFile, ModuleSet, Config, CurrentCodePath, - Dir, Command, DirSet) -> + Dir, Command, DirSet) -> case rebar_app_utils:is_skipped_app(Config, AppFile) of {Config1, {true, SkippedApp}} -> ?DEBUG("Skipping app: ~p~n", [SkippedApp]), @@ -158,11 +187,12 @@ process_dir1(Dir, Command, DirSet, Config0, CurrentCodePath, {Config1, Predirs} = acc_modules(Modules, preprocess, Config0, ModuleSetFile), - SubdirAssoc = remember_cwd_subdir(Dir, Predirs), + %% Remember associated pre-dirs (used for plugin lookup) + PredirsAssoc = remember_cwd_predirs(Dir, Predirs), %% Get the list of plug-in modules from rebar.config. These %% modules may participate in preprocess and postprocess. - {ok, PluginModules} = plugin_modules(Config1, SubdirAssoc), + {ok, PluginModules} = plugin_modules(Config1, PredirsAssoc), {Config2, PluginPredirs} = acc_modules(PluginModules, preprocess, Config1, ModuleSetFile), @@ -224,7 +254,7 @@ process_dir1(Dir, Command, DirSet, Config0, CurrentCodePath, %% Return the updated {config, dirset} as result Res. -remember_cwd_subdir(Cwd, Subdirs) -> +remember_cwd_predirs(Cwd, Predirs) -> Store = fun(Dir, Dict) -> case dict:find(Dir, Dict) of error -> @@ -235,11 +265,10 @@ remember_cwd_subdir(Cwd, Subdirs) -> ?ABORT("Internal consistency assertion failed.~n" "sub_dir ~s already associated with ~s.~n" "Duplicate sub_dirs or deps entries?", - [Dir, Existing]), - Dict + [Dir, Existing]) end end, - lists:foldl(Store, dict:new(), Subdirs). + lists:foldl(Store, dict:new(), Predirs). maybe_load_local_config(Dir, ParentConfig) -> %% We need to ensure we don't overwrite custom @@ -459,9 +488,9 @@ acc_modules([Module | Rest], Command, Config, File, Acc) -> %% %% Return a flat list of rebar plugin modules. %% -plugin_modules(Config, SubdirAssoc) -> +plugin_modules(Config, PredirsAssoc) -> Modules = lists:flatten(rebar_config:get_all(Config, plugins)), - plugin_modules(Config, SubdirAssoc, ulist(Modules)). + plugin_modules(Config, PredirsAssoc, ulist(Modules)). ulist(L) -> ulist(L, []). @@ -476,16 +505,16 @@ ulist([H | T], Acc) -> ulist(T, [H | Acc]) end. -plugin_modules(_Config, _SubdirAssoc, []) -> +plugin_modules(_Config, _PredirsAssoc, []) -> {ok, []}; -plugin_modules(Config, SubdirAssoc, Modules) -> +plugin_modules(Config, PredirsAssoc, Modules) -> FoundModules = [M || M <- Modules, code:which(M) =/= non_existing], - plugin_modules(Config, SubdirAssoc, FoundModules, Modules -- FoundModules). + plugin_modules(Config, PredirsAssoc, FoundModules, Modules -- FoundModules). -plugin_modules(_Config, _SubdirAssoc, FoundModules, []) -> +plugin_modules(_Config, _PredirsAssoc, FoundModules, []) -> {ok, FoundModules}; -plugin_modules(Config, SubdirAssoc, FoundModules, MissingModules) -> - {Loaded, NotLoaded} = load_plugin_modules(Config, SubdirAssoc, +plugin_modules(Config, PredirsAssoc, FoundModules, MissingModules) -> + {Loaded, NotLoaded} = load_plugin_modules(Config, PredirsAssoc, MissingModules), AllViablePlugins = FoundModules ++ Loaded, case NotLoaded =/= [] of @@ -499,7 +528,7 @@ plugin_modules(Config, SubdirAssoc, FoundModules, MissingModules) -> end, {ok, AllViablePlugins}. -load_plugin_modules(Config, SubdirAssoc, Modules) -> +load_plugin_modules(Config, PredirsAssoc, Modules) -> Cwd = rebar_utils:get_cwd(), PluginDir = case rebar_config:get_local(Config, plugin_dir, undefined) of undefined -> @@ -511,7 +540,7 @@ load_plugin_modules(Config, SubdirAssoc, Modules) -> %% Find relevant sources in base_dir and plugin_dir Erls = string:join([atom_to_list(M)++"\\.erl" || M <- Modules], "|"), RE = "^" ++ Erls ++ "\$", - BaseDir = get_plugin_base_dir(Cwd, SubdirAssoc), + BaseDir = get_plugin_base_dir(Cwd, PredirsAssoc), %% If a plugin is found both in base_dir and plugin_dir, the clash %% will provoke an error and we'll abort. Sources = rebar_utils:find_files(PluginDir, RE, false) @@ -523,8 +552,8 @@ load_plugin_modules(Config, SubdirAssoc, Modules) -> NotLoaded = [V || V <- Modules, FilterMissing(V)], {Loaded, NotLoaded}. -get_plugin_base_dir(Cwd, SubdirAssoc) -> - case dict:find(Cwd, SubdirAssoc) of +get_plugin_base_dir(Cwd, PredirsAssoc) -> + case dict:find(Cwd, PredirsAssoc) of {ok, BaseDir} -> BaseDir; error -> diff --git a/src/rebar_ct.erl b/src/rebar_ct.erl index 749d025..d5b1d26 100644 --- a/src/rebar_ct.erl +++ b/src/rebar_ct.erl @@ -39,6 +39,9 @@ -export([ct/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -53,6 +56,26 @@ ct(Config, File) -> %% =================================================================== %% Internal functions %% =================================================================== + +info(help, ct) -> + ?CONSOLE( + "Run common_test suites.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + "Valid command line options:~n" + " suites=foo,bar - run <test>/foo_SUITE and <test>/bar_SUITE~n" + " case=\"mycase\" - run individual test case foo_SUITE:mycase~n", + [ + {ct_dir, "itest"}, + {ct_log_dir, "test/logs"}, + {ct_extra_params, "-boot start_sasl -s myapp"}, + {ct_use_short_names, true} + ]). + run_test_if_present(TestDir, LogDir, Config, File) -> case filelib:is_dir(TestDir) of false -> diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl index 074e929..313deaa 100644 --- a/src/rebar_deps.erl +++ b/src/rebar_deps.erl @@ -38,6 +38,8 @@ 'delete-deps'/2, 'list-deps'/2]). +%% for internal use only +-export([info/2]). -record(dep, { dir, app, @@ -203,6 +205,40 @@ do_check_deps(Config) -> %% Internal functions %% =================================================================== +info(help, compile) -> + info_help("Display to be fetched dependencies"); +info(help, 'check-deps') -> + info_help("Display to be fetched dependencies"); +info(help, 'get-deps') -> + info_help("Fetch dependencies"); +info(help, 'update-deps') -> + info_help("Update fetched dependencies"); +info(help, 'delete-deps') -> + info_help("Delete fetched dependencies"); +info(help, 'list-deps') -> + info_help("List dependencies"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + "Valid command line options:~n" + " deps_dir=\"deps\" (override default or rebar.config deps_dir)~n", + [ + Description, + {deps_dir, "deps"}, + {deps, [application_name, + {application_name, "1.0.*"}, + {application_name, "1.0.*", + {git, "git://github.com/rebar/rebar.git", {branch, "master"}}}, + {application_name, "", + {git, "git://github.com/rebar/rebar.git", {branch, "master"}}, + [raw]}]} + ]). + %% Added because of trans deps, %% 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 diff --git a/src/rebar_dia_compiler.erl b/src/rebar_dia_compiler.erl index 51c075b..f81c734 100644 --- a/src/rebar_dia_compiler.erl +++ b/src/rebar_dia_compiler.erl @@ -28,6 +28,9 @@ -export([compile/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -46,6 +49,23 @@ clean(_Config, _AppFile) -> ok = rebar_file_utils:delete_each(GeneratedFiles), ok. +%% =================================================================== +%% Internal functions +%% =================================================================== + +info(help, compile) -> + info_help("Build Diameter (*.dia) sources"); +info(help, clean) -> + info_help("Delete generated Diameter files"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " {dia_opts, []} (see diameter_codegen:from_dict/4 documentation)~n", + [Description]). + -spec compile_dia(file:filename(), file:filename(), rebar_config:config()) -> ok. compile_dia(Source, Target, Config) -> diff --git a/src/rebar_edoc.erl b/src/rebar_edoc.erl index cf0239c..c828d27 100644 --- a/src/rebar_edoc.erl +++ b/src/rebar_edoc.erl @@ -39,6 +39,9 @@ -export([doc/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -71,6 +74,14 @@ doc(Config, File) -> %% Internal functions %% =================================================================== +info(help, doc) -> + ?CONSOLE( + "Generate Erlang program documentation.~n" + "~n" + "Valid rebar.config options:~n" + " {edoc_opts, []} (see edoc:application/3 documentation)~n", + []). + setup_code_path() -> %% Setup code path prior to calling edoc so that edown, asciiedoc, %% and the like can work properly when generating their own diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 91f8354..caef0d2 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -29,8 +29,9 @@ -export([compile/2, clean/2]). -%% for internal use by only eunit and qc --export([test_compile/3]). +%% for internal use only +-export([test_compile/3, + info/2]). -include("rebar.hrl"). @@ -116,8 +117,6 @@ clean(_Config, _AppFile) -> test_compile(Config, Cmd, OutDir) -> %% Obtain all the test modules for inclusion in the compile stage. - %% Notice: this could also be achieved with the following - %% rebar.config option: {test_compile_opts, [{src_dirs, ["src", "test"]}]} TestErls = rebar_utils:find_files("test", ".*\\.erl\$"), %% Copy source files to eunit dir for cover in case they are not directly @@ -165,6 +164,42 @@ test_compile(Config, Cmd, OutDir) -> %% Internal functions %% =================================================================== +info(help, compile) -> + info_help("Build *.erl, *.yrl, *.xrl, and *.mib sources"); +info(help, clean) -> + info_help("Delete *.erl, *.yrl, *.xrl, and *.mib build results"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n", + [ + Description, + {erl_opts, [no_debug_info, + {i, "myinclude"}, + {src_dirs, ["src", "src2", "src3"]}, + {platform_define, + "(linux|solaris|freebsd|darwin)", 'HAVE_SENDFILE'}, + {platform_define, "(linux|freebsd)", 'BACKLOG', 128}, + {platform_define, "R13", 'old_inets'}]}, + {erl_first_files, ["mymib1", "mymib2"]}, + {mib_opts, []}, + {mib_first_files, []}, + {xrl_opts, []}, + {xrl_first_files, []}, + {yrl_opts, []}, + {yrl_first_files, []} + ]). + test_compile_config(Config, Cmd) -> {Config1, TriqOpts} = triq_opts(Config), {Config2, PropErOpts} = proper_opts(Config1), diff --git a/src/rebar_erlydtl_compiler.erl b/src/rebar_erlydtl_compiler.erl index aef41c5..4449be6 100644 --- a/src/rebar_erlydtl_compiler.erl +++ b/src/rebar_erlydtl_compiler.erl @@ -96,6 +96,9 @@ -export([compile/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -123,11 +126,24 @@ compile(Config, _AppFile) -> true = code:set_path(OrigPath), Result. - %% =================================================================== %% Internal functions %% =================================================================== +info(help, compile) -> + ?CONSOLE( + "Build ErlyDtl (*.dtl) sources.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n", + [ + {erlydtl_opts, [{doc_root, "templates"}, + {out_dir, "ebin"}, + {source_ext, ".dtl"}, + {module_ext, "_dtl"}, + {recursive, true}]} + ]). + erlydtl_opts(Config) -> Opts = rebar_config:get(Config, erlydtl_opts, []), Tuples = [{K,V} || {K,V} <- Opts], @@ -135,11 +151,14 @@ erlydtl_opts(Config) -> [] -> [lists:keysort(1, Tuples)]; Lists -> - lists:map(fun(L) -> - lists:keysort(1, lists:foldl(fun({K,T}, Acc) -> - lists:keystore(K, 1, Acc, {K, T}) - end, Tuples, L)) - end, Lists) + lists:map( + fun(L) -> + lists:keysort(1, + lists:foldl( + fun({K,T}, Acc) -> + lists:keystore(K, 1, Acc, {K, T}) + end, Tuples, L)) + end, Lists) end. option(Opt, DtlOpts) -> diff --git a/src/rebar_escripter.erl b/src/rebar_escripter.erl index 706cf7c..0cc43ef 100644 --- a/src/rebar_escripter.erl +++ b/src/rebar_escripter.erl @@ -29,6 +29,9 @@ -export([escriptize/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). -include_lib("kernel/include/file.hrl"). @@ -108,6 +111,30 @@ clean(Config0, AppFile) -> %% Internal functions %% =================================================================== +info(help, escriptize) -> + info_help("Generate escript archive"); +info(help, clean) -> + info_help("Delete generated escript archive"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n", + [ + Description, + {escript_name, "application"}, + {escript_incl_apps, []}, + {escript_shebang, "#!/usr/bin/env escript\n"}, + {escript_comment, "%%\n"}, + {escript_emu_args, "%%! -pa application/application/ebin\n"} + ]). + get_app_beams([], Acc) -> Acc; get_app_beams([App | Rest], Acc) -> diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl index a7f4aca..cdc0787 100644 --- a/src/rebar_eunit.erl +++ b/src/rebar_eunit.erl @@ -61,7 +61,7 @@ %% Additionally, for projects that have separate folders for the core %% implementation, and for the unit tests, then the following %% <code>rebar.config</code> option can be provided: -%% <code>{test_compile_opts, [{src_dirs, ["dir"]}]}.</code>. +%% <code>{eunit_compile_opts, [{src_dirs, ["src", "dir"]}]}.</code>. %% @copyright 2009, 2010 Dave Smith %% ------------------------------------------------------------------- -module(rebar_eunit). @@ -69,6 +69,9 @@ -export([eunit/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). -define(EUNIT_DIR, ".eunit"). @@ -100,6 +103,40 @@ clean(_Config, _File) -> %% Internal functions %% =================================================================== +info(help, eunit) -> + info_help("Run eunit tests"); +info(help, clean) -> + Description = ?FMT("Delete eunit test dir (~s)", [?EUNIT_DIR]), + info_help(Description). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + " ~p~n" + "Valid command line options:~n" + " suites=\"foo,bar\" (Run tests in foo.erl, test/foo_tests.erl and~n" + " tests in bar.erl, test/bar_tests.erl)~n" + " tests=\"baz\" (For every existing suite, run the first test whose~n" + " name starts with bar and, if no such test exists,~n" + " run the test whose name starts with bar in the~n" + " suite's _tests module)~n", + [ + Description, + {eunit_opts, []}, + {eunit_compile_opts, []}, + {eunit_first_files, []}, + {cover_enabled, false}, + {cover_print_enabled, false}, + {cover_export_enabled, false} + ]). + run_eunit(Config, CodePath, SrcErls) -> %% Build a list of all the .beams in ?EUNIT_DIR -- use this for %% cover and eunit testing. Normally you can just tell cover diff --git a/src/rebar_lfe_compiler.erl b/src/rebar_lfe_compiler.erl index d288ca5..2a047d8 100644 --- a/src/rebar_lfe_compiler.erl +++ b/src/rebar_lfe_compiler.erl @@ -30,6 +30,9 @@ -export([compile/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -45,6 +48,14 @@ compile(Config, _AppFile) -> %% Internal functions %% =================================================================== +info(help, compile) -> + ?CONSOLE( + "Build Lisp Flavoured Erlang (*.lfe) sources.~n" + "~n" + "Valid rebar.config options:~n" + " erl_opts is reused.'~n", + []). + compile_lfe(Source, _Target, Config) -> case code:which(lfe_comp) of non_existing -> diff --git a/src/rebar_neotoma_compiler.erl b/src/rebar_neotoma_compiler.erl index 33f32e3..5607aa4 100644 --- a/src/rebar_neotoma_compiler.erl +++ b/src/rebar_neotoma_compiler.erl @@ -42,6 +42,9 @@ -export([compile/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% ============================================================================ @@ -60,6 +63,19 @@ compile(Config, _AppFile) -> %% Internal functions %% ============================================================================ +info(help, compile) -> + ?CONSOLE( + "Build Neotoma (*.peg) sources.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n", + [ + {neotom_opts, [{doc_root, "src"}, + {out_dir, "src"}, + {source_ext, ".peg"}, + {module_ext, ""}]} + ]). + neotoma_opts(Config) -> rebar_config:get(Config, neotoma_opts, []). diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl index a62f584..6c52336 100644 --- a/src/rebar_otp_app.erl +++ b/src/rebar_otp_app.erl @@ -29,6 +29,9 @@ -export([compile/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -82,11 +85,26 @@ clean(_Config, File) -> ok end. - %% =================================================================== %% Internal functions %% =================================================================== +info(help, compile) -> + info_help("Validate .app file"); +info(help, clean) -> + info_help("Delete .app file if generated from .app.src"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n", + [ + Description, + {validate_app_modules, true} + ]). + preprocess(Config, AppSrcFile) -> case rebar_app_utils:load_app_file(Config, AppSrcFile) of {ok, Config1, AppName, AppData} -> diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl index 06a79bc..36d741d 100644 --- a/src/rebar_port_compiler.erl +++ b/src/rebar_port_compiler.erl @@ -27,8 +27,11 @@ -module(rebar_port_compiler). -export([compile/2, - clean/2, - setup_env/1]). + clean/2]). + +%% for internal use only +-export([setup_env/1, + info/2]). -include("rebar.hrl"). @@ -149,6 +152,27 @@ setup_env(Config) -> %% Internal functions %% =================================================================== +info(help, compile) -> + info_help("Build port sources"); +info(help, clean) -> + info_help("Delete port build results"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n", + [ + Description, + {port_env, [{"CFLAGS", "$CFLAGS -Ifoo"}, + {"freebsd", "LDFLAGS", "$LDFLAGS -lfoo"}]}, + {port_specs, [{"priv/so_name.so", ["c_src/*.c"]}, + {"linux", "priv/hello_linux", ["c_src/hello_linux.c"]}, + {"linux", "priv/hello_linux", ["c_src/*.c"], [{env, []}]}]} + ]). + setup_env(Config, ExtraEnv) -> %% Extract environment values from the config (if specified) and %% merge with the default for this operating system. This enables diff --git a/src/rebar_protobuffs_compiler.erl b/src/rebar_protobuffs_compiler.erl index 7ef58d6..579ecfb 100644 --- a/src/rebar_protobuffs_compiler.erl +++ b/src/rebar_protobuffs_compiler.erl @@ -29,6 +29,9 @@ -export([compile/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). %% =================================================================== @@ -57,7 +60,6 @@ compile(Config, _AppFile) -> end end. - clean(_Config, _AppFile) -> %% Get a list of generated .beam and .hrl files and then delete them Protos = rebar_utils:find_files("src", ".*\\.proto$"), @@ -71,11 +73,24 @@ clean(_Config, _AppFile) -> delete_each(Targets) end. - %% =================================================================== %% Internal functions %% =================================================================== +info(help, compile) -> + info_help("Build Protobuffs (*.proto) sources"); +info(help, clean) -> + info_help("Delete Protobuffs (*.proto) build results"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " erl_opts is passed as compile_flags to " + "protobuffs_compile:scan_file/2~n", + [Description]). + protobuffs_is_present() -> code:which(protobuffs_compile) =/= non_existing. @@ -115,7 +130,7 @@ compile_each(Config, [{Proto, Beam, Hrl} | Rest]) -> ok = rebar_file_utils:mv(Hrl, "include"), ok; Other -> - ?ERROR("Protobuff compile of ~s failed: ~p\n", + ?ERROR("Protobuffs compile of ~s failed: ~p\n", [Proto, Other]), ?FAIL end; diff --git a/src/rebar_qc.erl b/src/rebar_qc.erl index 09e48e4..826ba9a 100644 --- a/src/rebar_qc.erl +++ b/src/rebar_qc.erl @@ -28,6 +28,9 @@ -export([qc/2, triq/2, eqc/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). -define(QC_DIR, ".qc"). @@ -57,6 +60,19 @@ clean(_Config, _File) -> %% Internal functions %% =================================================================== +info(help, qc) -> + ?CONSOLE( + "Test QuickCheck properties.~n" + "~n" + "Valid rebar.config options:~n" + " {qc_opts, [{qc_mod, module()}, Options]}~n" + " ~p~n" + " ~p~n", + [ + {qc_compile_opts, []}, + {qc_first_files, []} + ]). + -define(TRIQ_MOD, triq). -define(EQC_MOD, eqc). diff --git a/src/rebar_reltool.erl b/src/rebar_reltool.erl index 3c9b728..18b0702 100644 --- a/src/rebar_reltool.erl +++ b/src/rebar_reltool.erl @@ -30,6 +30,9 @@ overlay/2, clean/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). -include_lib("kernel/include/file.hrl"). @@ -80,6 +83,32 @@ clean(Config, ReltoolFile) -> %% Internal functions %% =================================================================== +info(help, generate) -> + info_help("Build release with reltool"); +info(help, clean) -> + info_help("Delete release"); +info(help, overlay) -> + info_help("Run reltool overlays only"). + +info_help(Description) -> + ?CONSOLE( + "~s.~n" + "~n" + "Valid rebar.config options:~n" + " ~n" + "Valid reltool.config options:~n" + " {sys, []}~n" + " {target_dir, \"target\"}~n" + " {overlay_vars, \"overlay\"}~n" + " {overlay, []}~n" + "Valid command line options:~n" + " target_dir=target~n" + " overlay_vars=VarsFile~n" + " dump_spec=1 (write reltool target spec to reltool.spec)~n", + [ + Description + ]). + check_vsn() -> %% TODO: use application:load and application:get_key once we require %% R14A or newer. There's no reltool.app before R14A. diff --git a/src/rebar_require_vsn.erl b/src/rebar_require_vsn.erl index 9a0a005..385f55c 100644 --- a/src/rebar_require_vsn.erl +++ b/src/rebar_require_vsn.erl @@ -33,6 +33,9 @@ -export([compile/2, eunit/2]). +%% for internal use only +-export([info/2]). + %% =================================================================== %% Public API %% =================================================================== @@ -47,6 +50,25 @@ eunit(Config, _) -> %% Internal functions %% ==================================================================== +info(help, compile) -> + info_help(); +info(help, eunit) -> + info_help(). + +info_help() -> + ?CONSOLE( + "Check required ERTS or OTP release version.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n", + [ + {require_erts_vsn, ".*"}, + {require_otp_vsn, ".*"}, + {require_min_otp_vsn, ".*"} + ]). + check_versions(Config) -> ErtsRegex = rebar_config:get(Config, require_erts_vsn, ".*"), ReOpts = [{capture, none}], diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl index 0e1eef1..e997975 100644 --- a/src/rebar_templater.erl +++ b/src/rebar_templater.erl @@ -35,6 +35,9 @@ -export([resolve_variables/2, render/2]). +%% for internal use only +-export([info/2]). + -include("rebar.hrl"). -define(TEMPLATE_RE, ".*\\.template\$"). @@ -81,6 +84,9 @@ resolve_variables([], Dict) -> resolve_variables([{Key, Value0} | Rest], Dict) when is_list(Value0) -> Value = render(list_to_binary(Value0), Dict), resolve_variables(Rest, dict:store(Key, Value, Dict)); +resolve_variables([{Key, {list, Dicts}} | Rest], Dict) when is_list(Dicts) -> + %% just un-tag it so mustache can use it + resolve_variables(Rest, dict:store(Key, Dicts, Dict)); resolve_variables([_Pair | Rest], Dict) -> resolve_variables(Rest, Dict). @@ -98,6 +104,27 @@ render(Bin, Context) -> %% Internal functions %% =================================================================== +info(help, create) -> + ?CONSOLE( + "Create skel based on template and vars.~n" + "~n" + "Valid command line options:~n" + " template= [var=foo,...]~n", []); +info(help, 'create-app') -> + ?CONSOLE( + "Create simple app skel.~n" + "~n" + "Valid command line options:~n" + " [appid=myapp]~n", []); +info(help, 'create-node') -> + ?CONSOLE( + "Create simple node skel.~n" + "~n" + "Valid command line options:~n" + " [nodeid=mynode]~n", []); +info(help, 'list-templates') -> + ?CONSOLE("List available templates.~n", []). + create1(Config, TemplateId) -> {AvailTemplates, Files} = find_templates(Config), ?DEBUG("Available templates: ~p\n", [AvailTemplates]), @@ -134,14 +161,14 @@ create1(Config, TemplateId) -> undefined -> Context0; File -> - case file:consult(File) of - {ok, Terms} -> - %% TODO: Cleanup/merge with similar code in rebar_reltool - M = fun(_Key, _Base, Override) -> Override end, - dict:merge(M, Context0, dict:from_list(Terms)); + case consult(load_file([], file, File)) of {error, Reason} -> ?ABORT("Unable to load template_vars from ~s: ~p\n", - [File, Reason]) + [File, Reason]); + Terms -> + %% TODO: Cleanup/merge with similar code in rebar_reltool + M = fun(_Key, _Base, Override) -> Override end, + dict:merge(M, Context0, dict:from_list(Terms)) end end, @@ -275,7 +302,7 @@ consult(Cont, Str, Acc) -> case Result of {ok, Tokens, _} -> {ok, Term} = erl_parse:parse_term(Tokens), - consult([], Remaining, [Term | Acc]); + consult([], Remaining, [maybe_dict(Term) | Acc]); {eof, _Other} -> lists:reverse(Acc); {error, Info, _} -> @@ -286,6 +313,13 @@ consult(Cont, Str, Acc) -> end. +maybe_dict({Key, {list, Dicts}}) -> + %% this is a 'list' element; a list of lists representing dicts + {Key, {list, [dict:from_list(D) || D <- Dicts]}}; +maybe_dict(Term) -> + Term. + + write_file(Output, Data, Force) -> %% determine if the target file already exists FileExists = filelib:is_regular(Output), diff --git a/src/rebar_upgrade.erl b/src/rebar_upgrade.erl index 14ea758..d18603c 100644 --- a/src/rebar_upgrade.erl +++ b/src/rebar_upgrade.erl @@ -32,6 +32,9 @@ -export(['generate-upgrade'/2]). +%% for internal use only +-export([info/2]). + -define(TMP, "_tmp"). %% ==================================================================== @@ -80,6 +83,13 @@ %% Internal functions %% ================================================================== +info(help, 'generate-upgrade') -> + ?CONSOLE("Build an upgrade package.~n" + "~n" + "Valid command line options:~n" + " previous_release=path~n", + []). + run_checks(Config, OldVerPath, ReltoolConfig) -> true = rebar_utils:prop_check(filelib:is_dir(OldVerPath), "Release directory doesn't exist (~p)~n", diff --git a/src/rebar_xref.erl b/src/rebar_xref.erl index a55d71d..8c0a872 100644 --- a/src/rebar_xref.erl +++ b/src/rebar_xref.erl @@ -37,6 +37,9 @@ -export([xref/2]). +%% for internal use only +-export([info/2]). + %% =================================================================== %% Public API %% =================================================================== @@ -100,6 +103,22 @@ xref(Config, _) -> %% Internal functions %% =================================================================== +info(help, xref) -> + ?CONSOLE( + "Run cross reference analysis.~n" + "~n" + "Valid rebar.config options:~n" + " ~p~n" + " ~p~n" + " ~p~n", + [ + {xref_warnings, false}, + {xref_checks, [exports_not_used, undefined_function_calls]}, + {xref_queries, + [{"(xc - uc) || (xu - x - b" + " - (\"mod\":\".*foo\"/\"4\"))",[]}]} + ]). + check_exports_not_used() -> {ok, UnusedExports0} = xref:analyze(xref, exports_not_used), UnusedExports = filter_away_ignored(UnusedExports0), |