ソースを参照

Merge branch 'master' into app-discover-profile-duplication

Conflicts:
	test/rebar_profiles_SUITE.erl
pull/350/head
Viacheslav V. Kovalev 10年前
コミット
33736f32a9
49個のファイルの変更1022行の追加370行の削除
  1. +2
    -2
      .gitignore
  2. +2
    -1
      .travis.yml
  3. +0
    -43
      Makefile
  4. +17
    -7
      README.md
  5. +220
    -0
      bootstrap
  6. +0
    -0
      bootstrap.bat
  7. +0
    -66
      bootstrap/bootstrap
  8. バイナリ
      bootstrap/rebar
  9. +49
    -19
      rebar.config
  10. +32
    -0
      rebar.lock
  11. +1
    -0
      src/rebar.app.src
  12. +6
    -1
      src/rebar3.erl
  13. +12
    -1
      src/rebar_api.erl
  14. +24
    -2
      src/rebar_app_discover.erl
  15. +14
    -1
      src/rebar_app_info.erl
  16. +1
    -1
      src/rebar_base_compiler.erl
  17. +1
    -2
      src/rebar_config.erl
  18. +8
    -2
      src/rebar_dir.erl
  19. +6
    -10
      src/rebar_erlc_compiler.erl
  20. +0
    -5
      src/rebar_otp_app.erl
  21. +5
    -0
      src/rebar_prv_common_test.erl
  22. +14
    -10
      src/rebar_prv_compile.erl
  23. +1
    -1
      src/rebar_prv_cover.erl
  24. +3
    -0
      src/rebar_prv_dialyzer.erl
  25. +33
    -24
      src/rebar_prv_erlydtl_compiler.erl
  26. +37
    -25
      src/rebar_prv_escriptize.erl
  27. +4
    -0
      src/rebar_prv_eunit.erl
  28. +102
    -52
      src/rebar_prv_install_deps.erl
  29. +16
    -15
      src/rebar_prv_lock.erl
  30. +2
    -1
      src/rebar_prv_release.erl
  31. +7
    -6
      src/rebar_prv_shell.erl
  32. +2
    -1
      src/rebar_prv_tar.erl
  33. +84
    -0
      src/rebar_prv_unlock.erl
  34. +4
    -2
      src/rebar_prv_update.erl
  35. +20
    -11
      src/rebar_prv_upgrade.erl
  36. +5
    -17
      src/rebar_prv_xref.erl
  37. +27
    -2
      src/rebar_state.erl
  38. +26
    -8
      src/rebar_templater.erl
  39. +0
    -8
      src/rebar_utils.erl
  40. +1
    -1
      test/mock_pkg_resource.erl
  41. +8
    -5
      test/rebar_compile_SUITE.erl
  42. +6
    -6
      test/rebar_eunit_SUITE.erl
  43. +79
    -2
      test/rebar_install_deps_SUITE.erl
  44. +42
    -3
      test/rebar_profiles_SUITE.erl
  45. +4
    -3
      test/rebar_test_utils.erl
  46. +40
    -0
      test/rebar_unlock_SUITE.erl
  47. +40
    -0
      test/rebar_unlock_SUITE_data/rebar.lock
  48. +13
    -2
      test/rebar_upgrade_SUITE.erl
  49. +2
    -2
      test/rebar_xref_SUITE.erl

+ 2
- 2
.gitignore ファイルの表示

@ -1,8 +1,9 @@
rebar3
_build
.depsolver_plt .depsolver_plt
*.beam *.beam
test/*_data test/*_data
logs logs
rebar3
/rebar /rebar
*~ *~
*.orig *.orig
@ -13,6 +14,5 @@ rebar3
/.eunit /.eunit
/deps /deps
/.rebar /.rebar
rebar.lock
priv/templates/*.dtl.erl priv/templates/*.dtl.erl
ebin ebin

+ 2
- 1
.travis.yml ファイルの表示

@ -3,7 +3,8 @@ otp_release:
- 17.0 - 17.0
- R16B03-1 - R16B03-1
- R15B03 - R15B03
script: make travis
before_script: "./bootstrap"
script: "./rebar3 ct"
branches: branches:
only: only:
- master - master

+ 0
- 43
Makefile ファイルの表示

@ -1,43 +0,0 @@
.PHONY: clean xref_warnings deps test
REBAR=$(PWD)/rebar3
RETEST=$(PWD)/deps/retest/retest
DEPS_PLT=$(CURDIR)/.depsolver_plt
all:
@./bootstrap/rebar get-deps compile escriptize
clean:
@rm -rf rebar3 ebin/*.beam inttest/rt.work rt.work .eunit
@rm -f .rebarinfo
distclean: clean
@rm -rf deps
debug:
@./bootstrap/bootstrap debug
check: debug xref deps test
xref:
@./rebar3 xref
$(DEPS_PLT):
@echo Building local erts plt at $(DEPS_PLT)
@echo
dialyzer --output_plt $(DEPS_PLT) --build_plt \
--apps erts kernel stdlib -r deps
dialyzer: $(DEPS_PLT)
dialyzer --fullpath --plt $(DEPS_PLT) -Wno_opaque -Wrace_conditions -r ./ebin
binary: VSN = $(shell ./rebar3 -V)
binary: clean all
@cp rebar3 ../rebar.wiki/rebar
(cd ../rebar.wiki && git commit -m "Update $(VSN)" rebar)
test:
rebar ct
travis: all test

+ 17
- 7
README.md ファイルの表示

@ -73,7 +73,8 @@ Example:
-behaviour(rebar_provider). -behaviour(rebar_provider).
-export([init/1, -export([init/1,
do/1]).
do/1,
format_error/1]).
-define(PROVIDER, something). -define(PROVIDER, something).
-define(DEPS, []). -define(DEPS, []).
@ -98,6 +99,10 @@ init(State) ->
do(State) -> do(State) ->
%% Do something %% Do something
{ok, State}. {ok, State}.
-spec format_error(any()) -> iolist().
format_error(Reason) ->
io_lib:format("~p", [Reason]).
``` ```
@ -118,16 +123,21 @@ You can download a pre-built binary version of rebar3 based on the last commit f
https://s3.amazonaws.com/rebar3/rebar3 https://s3.amazonaws.com/rebar3/rebar3
#### Building rebar
#### Bootstrapping rebar3
```sh ```sh
$ git clone https://github.com/rebar/rebar3 $ git clone https://github.com/rebar/rebar3
$ cd rebar3 $ cd rebar3
$ ./bootstrap/bootstrap
==> rebar (compile)
Congratulations! You now have a self-contained script called "rebar3" in
your current working directory. Place this script anywhere in your path
and you can use rebar to build OTP-compliant apps.
$ ./bootstrap
```
### Developing on rebar3
When developing you can simply run `escriptize` to build your changes but the new escript is under `_build/default/bin/rebar3`
```sh
$ ./rebar3 escriptize
$ _build/default/bin/rebar3
``` ```

+ 220
- 0
bootstrap ファイルの表示

@ -0,0 +1,220 @@
#!/usr/bin/env escript
%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
%% ex: ft=erlang ts=4 sw=4 et
main(_Args) ->
%% Fetch and build deps required to build rebar3
BaseDeps = [{providers, []}
,{getopt, []}
,{erlware_commons, ["ec_dictionary.erl", "ec_vsn.erl"]}],
Deps = get_deps(),
[fetch_and_compile(Dep, Deps) || Dep <- BaseDeps],
%% Build rebar3 modules with compile:file
bootstrap_rebar3(),
%% Build rebar.app from rebar.app.src
{ok, App} = rebar_app_info:new(rebar, "3.0.0", filename:absname("_build/default/lib/rebar/")),
rebar_otp_app:compile(rebar_state:new(), App),
%% Because we are compiling files that are loaded already we want to silence
%% not_purged errors in rebar_erlc_compiler:opts_changed/1
error_logger:tty(false),
setup_env(),
os:putenv("REBAR_PROFILE", "bootstrap"),
{ok, State} = rebar3:run(["compile"]),
reset_env(),
os:putenv("REBAR_PROFILE", ""),
%% Build erlydtl files (a hook on compile in the default profile) and escript file
DepsPaths = rebar_state:code_paths(State, all_deps),
code:add_pathsa(DepsPaths),
rebar3:run(["clean", "-a"]),
rebar3:run(["escriptize"]),
%% Done with compile, can turn back on error logger
error_logger:tty(true),
%% Finally, update executable perms for our script on *nix,
%% or write out script files on win32.
ec_file:copy("_build/default/bin/rebar3", "./rebar3"),
case os:type() of
{unix,_} ->
[] = os:cmd("chmod u+x rebar3"),
ok;
{win32,_} ->
write_windows_scripts(),
ok;
_ ->
ok
end.
fetch_and_compile({Name, ErlFirstFiles}, Deps) ->
{Name, _, Repo} = lists:keyfind(Name, 1, Deps),
ok = fetch(Repo, Name),
compile(Name, ErlFirstFiles).
fetch({git, Url, Source}, App) ->
Dir = filename:join([filename:absname("_build/default/lib/"), App]),
case filelib:is_dir(Dir) of
true ->
true = code:add_path(filename:join(Dir, "ebin")),
ok;
false ->
fetch_source(Dir, Url, Source),
ok
end.
fetch_source(Dir, Url, {ref, Ref}) ->
ok = filelib:ensure_dir(Dir),
os:cmd(io_lib:format("git clone ~s ~s", [Url, Dir])),
{ok, Cwd} = file:get_cwd(),
file:set_cwd(Dir),
os:cmd(io_lib:format("git checkout -q ~s", [Ref])),
file:set_cwd(Cwd);
fetch_source(Dir, Url, {_, Branch}) ->
ok = filelib:ensure_dir(Dir),
os:cmd(io_lib:format("git clone ~s ~s -b ~s --single-branch",
[Url, Dir, Branch])).
compile(App, FirstFiles) ->
Dir = filename:join(filename:absname("_build/default/lib/"), App),
filelib:ensure_dir(filename:join([Dir, "ebin", "dummy.beam"])),
code:add_path(filename:join(Dir, "ebin")),
FirstFilesPaths = [filename:join([Dir, "src", Module]) || Module <- FirstFiles],
Sources = FirstFilesPaths ++ filelib:wildcard(filename:join([Dir, "src", "*.erl"])),
[compile_file(X, [{i, filename:join(Dir, "include")}
,{outdir, filename:join(Dir, "ebin")}
,return | additional_defines()]) || X <- Sources].
compile_file(File, Opts) ->
case compile:file(File, Opts) of
{ok, _Mod} ->
ok;
{ok, _Mod, []} ->
ok;
{ok, _Mod, Ws} ->
io:format("~s~n", [format_warnings(File, Ws)]),
halt(1);
{error, Es, Ws} ->
io:format("~s ~s~n", [format_errors(File, Es), format_warnings(File, Ws)]),
halt(1)
end.
bootstrap_rebar3() ->
filelib:ensure_dir("_build/default/lib/rebar/ebin/dummy.beam"),
code:add_path("_build/default/lib/rebar/ebin/"),
file:make_symlink(filename:absname("src"), filename:absname("_build/default/lib/rebar/src")),
Sources = ["src/rebar_resource.erl" | filelib:wildcard("src/*.erl")],
[compile_file(X, [{outdir, "_build/default/lib/rebar/ebin/"}
,return | additional_defines()]) || X <- Sources],
code:add_patha(filename:absname("_build/default/lib/rebar/ebin")).
setup_env() ->
%% We don't need or want erlydtl or relx providers loaded yet
application:load(rebar),
{ok, Providers} = application:get_env(rebar, providers),
Providers1 = Providers -- [rebar_prv_erlydtl_compiler,
rebar_prv_release,
rebar_prv_tar],
application:set_env(rebar, providers, Providers1).
reset_env() ->
%% Reset the env so we get all providers and can build erlydtl files
application:unset_env(rebar, providers),
application:unload(rebar),
application:load(rebar).
write_windows_scripts() ->
CmdScript=
"@echo off\r\n"
"setlocal\r\n"
"set rebarscript=%~f0\r\n"
"escript.exe \"%rebarscript:.cmd=%\" %*\r\n",
ok = file:write_file("rebar3.cmd", CmdScript).
get_deps() ->
case file:consult("rebar.lock") of
{ok, [Deps]} ->
[{binary_to_atom(Name, utf8), "", Source} || {Name, Source, _Level} <- Deps];
_ ->
{ok, Config} = file:consult("rebar.config"),
proplists:get_value(deps, Config)
end.
format_errors(Source, Errors) ->
format_errors(Source, "", Errors).
format_warnings(Source, Warnings) ->
format_warnings(Source, Warnings, []).
format_warnings(Source, Warnings, Opts) ->
Prefix = case lists:member(warnings_as_errors, Opts) of
true -> "";
false -> "Warning: "
end,
format_errors(Source, Prefix, Warnings).
format_errors(_MainSource, Extra, Errors) ->
[begin
[format_error(Source, Extra, Desc) || Desc <- Descs]
end
|| {Source, Descs} <- Errors].
format_error(AbsSource, Extra, {{Line, Column}, Mod, Desc}) ->
ErrorDesc = Mod:format_error(Desc),
io_lib:format("~s:~w:~w: ~s~s~n", [AbsSource, Line, Column, Extra, ErrorDesc]);
format_error(AbsSource, Extra, {Line, Mod, Desc}) ->
ErrorDesc = Mod:format_error(Desc),
io_lib:format("~s:~w: ~s~s~n", [AbsSource, Line, Extra, ErrorDesc]);
format_error(AbsSource, Extra, {Mod, Desc}) ->
ErrorDesc = Mod:format_error(Desc),
io_lib:format("~s: ~s~s~n", [AbsSource, Extra, ErrorDesc]).
additional_defines() ->
[{d, D} || {Re, D} <- [{"^[0-9]+", namespaced_types}, {"^R1[4|5]", deprecated_crypto}], is_otp_release(Re)].
is_otp_release(ArchRegex) ->
case re:run(otp_release(), ArchRegex, [{capture, none}]) of
match ->
true;
nomatch ->
false
end.
otp_release() ->
otp_release1(erlang:system_info(otp_release)).
%% If OTP <= R16, otp_release is already what we want.
otp_release1([$R,N|_]=Rel) when is_integer(N) ->
Rel;
%% If OTP >= 17.x, erlang:system_info(otp_release) returns just the
%% major version number, we have to read the full version from
%% a file. See http://www.erlang.org/doc/system_principles/versions.html
%% Read vsn string from the 'OTP_VERSION' file and return as list without
%% the "\n".
otp_release1(Rel) ->
File = filename:join([code:root_dir(), "releases", Rel, "OTP_VERSION"]),
{ok, Vsn} = file:read_file(File),
%% It's fine to rely on the binary module here because we can
%% be sure that it's available when the otp_release string does
%% not begin with $R.
Size = byte_size(Vsn),
%% The shortest vsn string consists of at least two digits
%% followed by "\n". Therefore, it's safe to assume Size >= 3.
case binary:part(Vsn, {Size, -3}) of
<<"**\n">> ->
%% The OTP documentation mentions that a system patched
%% using the otp_patch_apply tool available to licensed
%% customers will leave a '**' suffix in the version as a
%% flag saying the system consists of application versions
%% from multiple OTP versions. We ignore this flag and
%% drop the suffix, given for all intents and purposes, we
%% cannot obtain relevant information from it as far as
%% tooling is concerned.
binary:bin_to_list(Vsn, {0, Size - 3});
_ ->
binary:bin_to_list(Vsn, {0, Size - 1})
end.

bootstrap/bootstrap.bat → bootstrap.bat ファイルの表示


+ 0
- 66
bootstrap/bootstrap ファイルの表示

@ -1,66 +0,0 @@
#!/usr/bin/env escript
%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
%% ex: ft=erlang ts=4 sw=4 et
main(Args) ->
case lists:member("--help", Args) of
true ->
usage(),
halt(0);
false ->
ok
end,
%% Check for force=1 flag to force a rebuild
case lists:member("force=1", Args) of
true ->
rm("ebin/*.beam");
false ->
rm("ebin/rebar.beam")
end,
%% Extract the system info of the version of OTP we use to compile rebar
os:cmd("./bootstrap/rebar get-deps compile escriptize"),
%% Finally, update executable perms for our script on *nix,
%% or write out script files on win32.
case os:type() of
{unix,_} ->
[] = os:cmd("chmod u+x rebar3"),
ok;
{win32,_} ->
write_windows_scripts(),
ok;
_ ->
ok
end,
%% Add a helpful message
io:format("Congratulations! You now have a self-contained script called"
" \"rebar3\" in\n"
"your current working directory. "
"Place this script anywhere in your path\n"
"and you can use rebar to build OTP-compliant apps.\n").
usage() ->
io:format("Usage: bootstrap [OPTION]...~n"),
io:format(" force=1 unconditional build~n"),
io:format(" debug add debug information~n").
rm(Path) ->
NativePath = filename:nativename(Path),
Cmd = case os:type() of
{unix,_} -> "rm -f ";
{win32,_} -> "del /q "
end,
[] = os:cmd(Cmd ++ NativePath),
ok.
write_windows_scripts() ->
CmdScript=
"@echo off\r\n"
"setlocal\r\n"
"set rebarscript=%~f0\r\n"
"escript.exe \"%rebarscript:.cmd=%\" %*\r\n",
ok = file:write_file("rebar.cmd", CmdScript).

バイナリ
bootstrap/rebar ファイルの表示


+ 49
- 19
rebar.config ファイルの表示

@ -1,15 +1,31 @@
%% -*- mode: erlang;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 %% ex: ts=4 sw=4 ft=erlang et
%% escript_incl_extra is for internal rebar-private use only.
%% Do not use outside rebar. Config interface is not stable.
{escript_incl_extra, [{"priv/templates/*", "."}, {"rebar/include/*", "."}]}.
{deps, [
{erlware_commons, "",
{git, "https://github.com/erlware/erlware_commons.git",
{branch, "master"}}},
{providers, "",
{git, "https://github.com/tsloughter/providers.git",
{tag, "v1.3.1"}}},
{erlydtl, "",
{git, "https://github.com/erlydtl/erlydtl.git",
{branch, "master"}}},
{relx, "",
{git, "https://github.com/erlware/relx.git",
{branch, "master"}}},
{getopt, "",
{git, "https://github.com/jcomellas/getopt.git",
{branch, "master"}}}]}.
{escript_incl_apps, {escript_incl_apps,
[getopt, merl, erlydtl, erlware_commons, relx, providers, rebar]}. [getopt, merl, erlydtl, erlware_commons, relx, providers, rebar]}.
{escript_top_level_app, rebar}. {escript_top_level_app, rebar}.
{escript_name, rebar3}. {escript_name, rebar3}.
{escript_emu_args, "%%! +sbtu +A0\n"}. {escript_emu_args, "%%! +sbtu +A0\n"}.
%% escript_incl_extra is for internal rebar-private use only.
%% Do not use outside rebar. Config interface is not stable.
{escript_incl_extra, [{"priv/templates/*", "."}, {"rebar/include/*", "."}]}.
{erl_opts, {erl_opts,
[{platform_define, "R14", no_callback_support}, [{platform_define, "R14", no_callback_support},
@ -18,23 +34,37 @@
debug_info, debug_info,
warnings_as_errors]}. warnings_as_errors]}.
{deps, [
{erlware_commons, ".*",
{git, "https://github.com/erlware/erlware_commons.git",
{branch, "master"}}},
{providers, "",
{git, "https://github.com/tsloughter/providers.git",
{tag, "v1.3.1"}}},
{erlydtl, ".*",
{git, "https://github.com/erlydtl/erlydtl.git",
{tag, "0.10.0"}}},
{relx, "",
{git, "https://github.com/erlware/relx.git",
{branch, "master"}}},
{getopt, "", {git, "https://github.com/jcomellas/getopt.git", {branch, "master"}}},
{meck, "", {git, "https://github.com/eproxus/meck.git", {tag, "0.8.2"}}}]}.
{erlydtl_opts, [{doc_root, "priv/templates"}, {erlydtl_opts, [{doc_root, "priv/templates"},
{compiler_options, [report, return, debug_info]}]}. {compiler_options, [report, return, debug_info]}]}.
{dialyzer_plt_apps, [common_test, dialyzer, erlydtl, eunit, snmp]}. {dialyzer_plt_apps, [common_test, dialyzer, erlydtl, eunit, snmp]}.
{provider_hooks, [{post, [{compile, {erlydtl, compile}}]}]}.
%% Profiles
{profiles, [{test,
[{deps, [
{meck, "", {git, "https://github.com/eproxus/meck.git", {tag, "0.8.2"}}}
]}
]
},
%% We don't want erlydtl to attempt to run on the first compile pass to bootstrap
{bootstrap, [{overrides, [{override, relx, [{provider_hooks, [{post, []}]}]}]},
{provider_hooks, [{post, []}]}]}
]}.
%% Overrides
{overrides, [{override, erlware_commons, [{plugins, []}]},
{override, merl, [{pre_hooks, [{"(linux|darwin|solaris)", compile, "make -C \"$REBAR_DEPS_DIR/merl\" all -W test"},
{"(freebsd|netbsd|openbsd)", compile, "gmake -C \"$REBAR_DEPS_DIR/merl\" all"},
{"win32", compile, "make -C \"%REBAR_DEPS_DIR%/merl\" all -W test"},
{eunit,
"erlc -I include/erlydtl_preparser.hrl -o test"
" test/erlydtl_extension_testparser.yrl"},
{"(linux|darwin|solaris)", eunit, "make -C \"$REBAR_DEPS_DIR/merl\" test"},
{"(freebsd|netbsd|openbsd)", eunit, "gmake -C \"$REBAR_DEPS_DIR/merl\" test"},
{"win32", eunit, "make -C \"%REBAR_DEPS_DIR%/merl\" test"}
]}]},
{override, erlydtl, [{pre_hooks, []}]}
]}.

+ 32
- 0
rebar.lock ファイルの表示

@ -0,0 +1,32 @@
[{<<"rebar_vsn_plugin">>,
{git,"https://github.com/erlware/rebar_vsn_plugin.git",
{ref,"fd40c960c7912193631d948fe962e1162a8d1334"}},
1},
{<<"merl">>,
{git,"git://github.com/erlydtl/merl.git",
{ref,"750b09d44425f435ff579a4d28bf5844bb5b4ef1"}},
1},
{<<"eunit_formatters">>,
{git,"git://github.com/seancribbs/eunit_formatters",
{ref,"2c73eb6e46b0863f19507857b386a48a53aaf141"}},
1},
{<<"relx">>,
{git,"https://github.com/erlware/relx.git",
{ref,"f8af9f5cd9f70ff43a043fe274dda4e56be82a2d"}},
0},
{<<"providers">>,
{git,"https://github.com/tsloughter/providers.git",
{ref,"7563ba7e916d5a35972b25b3aa1945ffe0a8e7a5"}},
0},
{<<"getopt">>,
{git,"https://github.com/jcomellas/getopt.git",
{ref,"626698975e63866156159661d100785d65eab6f9"}},
0},
{<<"erlydtl">>,
{git,"https://github.com/erlydtl/erlydtl.git",
{ref,"a4ac28680d6e066aabf86b3be9f073352a1a4d40"}},
0},
{<<"erlware_commons">>,
{git,"https://github.com/erlware/erlware_commons.git",
{ref,"ef0d252b11c863f9c228af2fe93a4e42fba2f7f3"}},
0}].

+ 1
- 0
src/rebar.app.src ファイルの表示

@ -49,6 +49,7 @@
rebar_prv_report, rebar_prv_report,
rebar_prv_shell, rebar_prv_shell,
rebar_prv_tar, rebar_prv_tar,
rebar_prv_unlock,
rebar_prv_update, rebar_prv_update,
rebar_prv_upgrade, rebar_prv_upgrade,
rebar_prv_version, rebar_prv_version,

+ 6
- 1
src/rebar3.erl ファイルの表示

@ -27,6 +27,7 @@
-module(rebar3). -module(rebar3).
-export([main/1, -export([main/1,
run/1,
run/2, run/2,
global_option_spec_list/0, global_option_spec_list/0,
init_config/0, init_config/0,
@ -114,6 +115,8 @@ run_aux(State, RawArgs) ->
State2 = case os:getenv("REBAR_PROFILE") of State2 = case os:getenv("REBAR_PROFILE") of
false -> false ->
State; State;
"" ->
State;
Profile -> Profile ->
rebar_state:apply_profiles(State, [list_to_atom(Profile)]) rebar_state:apply_profiles(State, [list_to_atom(Profile)])
end, end,
@ -134,7 +137,9 @@ run_aux(State, RawArgs) ->
{Task, Args} = parse_args(RawArgs), {Task, Args} = parse_args(RawArgs),
rebar_core:init_command(rebar_state:command_args(State7, Args), Task).
State8 = rebar_state:code_paths(State7, default, code:get_path()),
rebar_core:init_command(rebar_state:command_args(State8, Args), Task).
init_config() -> init_config() ->
%% Initialize logging system %% Initialize logging system

+ 12
- 1
src/rebar_api.erl ファイルの表示

@ -8,7 +8,9 @@
debug/2, info/2, warn/2, error/2, debug/2, info/2, warn/2, error/2,
expand_env_variable/3, expand_env_variable/3,
get_arch/0, get_arch/0,
wordsize/0]).
wordsize/0,
add_deps_to_path/1,
restore_code_path/1]).
-export_type([rebar_dict/0, rebar_digraph/0]). -export_type([rebar_dict/0, rebar_digraph/0]).
@ -48,3 +50,12 @@ get_arch() ->
wordsize() -> wordsize() ->
rebar_utils:wordsize(). rebar_utils:wordsize().
%% Add deps to the code path
add_deps_to_path(State) ->
code:add_pathsa(rebar_state:code_paths(State, all_deps)).
%% Revert to only having the beams necessary for running rebar3 and plugins in the path
restore_code_path(State) ->
rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)).

+ 24
- 2
src/rebar_app_discover.erl ファイルの表示

@ -37,12 +37,13 @@ merge_deps(AppInfo, State) ->
Default = rebar_state:default(State), Default = rebar_state:default(State),
CurrentProfiles = rebar_state:current_profiles(State), CurrentProfiles = rebar_state:current_profiles(State),
Name = rebar_app_info:name(AppInfo), Name = rebar_app_info:name(AppInfo),
C = rebar_config:consult(rebar_app_info:dir(AppInfo)),
C = project_app_config(AppInfo, State),
%% We reset the opts here to default so no profiles are applied multiple times %% We reset the opts here to default so no profiles are applied multiple times
AppState = rebar_state:apply_overrides( AppState = rebar_state:apply_overrides(
rebar_state:apply_profiles( rebar_state:apply_profiles(
rebar_state:new(rebar_state:opts(State, Default), C, rebar_app_info:dir(AppInfo)), CurrentProfiles), Name),
rebar_state:new(reset_hooks(rebar_state:opts(State, Default)), C,
rebar_app_info:dir(AppInfo)), CurrentProfiles), Name),
AppInfo1 = rebar_app_info:state(AppInfo, AppState), AppInfo1 = rebar_app_info:state(AppInfo, AppState),
State1 = lists:foldl(fun(Profile, StateAcc) -> State1 = lists:foldl(fun(Profile, StateAcc) ->
@ -56,6 +57,27 @@ merge_deps(AppInfo, State) ->
{AppInfo1, State1}. {AppInfo1, State1}.
project_app_config(AppInfo, State) ->
C = rebar_config:consult(rebar_app_info:dir(AppInfo)),
Dir = rebar_app_info:dir(AppInfo),
maybe_reset_hooks(C, Dir, State).
%% Here we check if the app is at the root of the project.
%% If it is, then drop the hooks from the config so they aren't run twice
maybe_reset_hooks(C, Dir, State) ->
case filename:dirname(rebar_dir:root_dir(State)) of
Dir ->
C1 = proplists:delete(provider_hooks, C),
proplists:delete(hooks, C1);
_ ->
C
end.
reset_hooks(State) ->
lists:foldl(fun(Key, StateAcc) ->
rebar_state:set(StateAcc, Key, [])
end, State, [post_hooks, pre_hooks, provider_hooks]).
-spec all_app_dirs(list(file:name())) -> list(file:name()). -spec all_app_dirs(list(file:name())) -> list(file:name()).
all_app_dirs(LibDirs) -> all_app_dirs(LibDirs) ->
lists:flatmap(fun(LibDir) -> lists:flatmap(fun(LibDir) ->

+ 14
- 1
src/rebar_app_info.erl ファイルの表示

@ -61,7 +61,7 @@
%%============================================================================ %%============================================================================
%% types %% types
%%============================================================================ %%============================================================================
-type t() :: record(app_info_t).
-type t() :: #app_info_t{}.
%%============================================================================ %%============================================================================
%% API %% API
@ -157,6 +157,19 @@ app_file(AppInfo=#app_info_t{}, AppFile) ->
AppInfo#app_info_t{app_file=AppFile}. AppInfo#app_info_t{app_file=AppFile}.
-spec app_details(t()) -> list(). -spec app_details(t()) -> list().
app_details(AppInfo=#app_info_t{app_details=[]}) ->
AppFile = case app_file(AppInfo) of
undefined ->
app_file_src(AppInfo);
File ->
File
end,
case file:consult(AppFile) of
{ok, [{application, _, AppDetails}]} ->
AppDetails;
_ ->
[]
end;
app_details(#app_info_t{app_details=AppDetails}) -> app_details(#app_info_t{app_details=AppDetails}) ->
AppDetails. AppDetails.

+ 1
- 1
src/rebar_base_compiler.erl ファイルの表示

@ -114,7 +114,7 @@ compile_each([Source | Rest], Config, CompileFn) ->
skipped -> skipped ->
?DEBUG("~sSkipped ~s", [rebar_utils:indent(1), filename:basename(Source)]); ?DEBUG("~sSkipped ~s", [rebar_utils:indent(1), filename:basename(Source)]);
Error -> Error ->
?INFO("Compiling ~s failed:",
?ERROR("Compiling ~s failed",
[maybe_absname(Config, Source)]), [maybe_absname(Config, Source)]),
maybe_report(Error), maybe_report(Error),
?DEBUG("Compilation failed: ~p", [Error]), ?DEBUG("Compilation failed: ~p", [Error]),

+ 1
- 2
src/rebar_config.erl ファイルの表示

@ -57,7 +57,6 @@ consult_file(File) ->
{ok, Terms} = consult_and_eval(File, Script), {ok, Terms} = consult_and_eval(File, Script),
Terms; Terms;
false -> false ->
?DEBUG("Consult config file ~p", [File]),
try_consult(File) try_consult(File)
end end
end. end.
@ -70,7 +69,7 @@ merge_locks(Config, [[]]) ->
Config; Config;
%% lockfile with entries %% lockfile with entries
merge_locks(Config, [Locks]) -> merge_locks(Config, [Locks]) ->
{deps, ConfigDeps} = lists:keyfind(deps, 1, Config),
ConfigDeps = proplists:get_value(deps, Config, []),
%% We want the top level deps only from the lock file. %% We want the top level deps only from the lock file.
%% This ensures deterministic overrides for configs. %% This ensures deterministic overrides for configs.
%% Then check if any new deps have been added to the config %% Then check if any new deps have been added to the config

+ 8
- 2
src/rebar_dir.erl ファイルの表示

@ -1,8 +1,10 @@
-module(rebar_dir). -module(rebar_dir).
-export([base_dir/1, -export([base_dir/1,
profile_dir/2,
deps_dir/1, deps_dir/1,
deps_dir/2, deps_dir/2,
root_dir/1,
checkouts_dir/1, checkouts_dir/1,
checkouts_dir/2, checkouts_dir/2,
plugins_dir/1, plugins_dir/1,
@ -24,7 +26,10 @@
-spec base_dir(rebar_state:t()) -> file:filename_all(). -spec base_dir(rebar_state:t()) -> file:filename_all().
base_dir(State) -> base_dir(State) ->
Profiles = rebar_state:current_profiles(State),
profile_dir(State, rebar_state:current_profiles(State)).
-spec profile_dir(rebar_state:t(), [atom()]) -> file:filename_all().
profile_dir(State, Profiles) ->
ProfilesStrings = case [ec_cnv:to_list(P) || P <- Profiles] of ProfilesStrings = case [ec_cnv:to_list(P) || P <- Profiles] of
["default"] -> ["default"]; ["default"] -> ["default"];
%% drop `default` from the profile dir if it's implicit and reverse order %% drop `default` from the profile dir if it's implicit and reverse order
@ -34,6 +39,7 @@ base_dir(State) ->
ProfilesDir = string:join(ProfilesStrings, "+"), ProfilesDir = string:join(ProfilesStrings, "+"),
filename:join(rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR), ProfilesDir). filename:join(rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR), ProfilesDir).
-spec deps_dir(rebar_state:t()) -> file:filename_all(). -spec deps_dir(rebar_state:t()) -> file:filename_all().
deps_dir(State) -> deps_dir(State) ->
filename:join(base_dir(State), rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR)). filename:join(base_dir(State), rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR)).
@ -43,7 +49,7 @@ deps_dir(DepsDir, App) ->
filename:join(DepsDir, App). filename:join(DepsDir, App).
root_dir(State) -> root_dir(State) ->
rebar_state:get(State, root_dir, ?DEFAULT_ROOT_DIR).
filename:absname(rebar_state:get(State, root_dir, ?DEFAULT_ROOT_DIR)).
-spec checkouts_dir(rebar_state:t()) -> file:filename_all(). -spec checkouts_dir(rebar_state:t()) -> file:filename_all().
checkouts_dir(State) -> checkouts_dir(State) ->

+ 6
- 10
src/rebar_erlc_compiler.erl ファイルの表示

@ -148,8 +148,8 @@ doterl_compile(Config, Dir, OutDir, MoreSources, ErlOpts) ->
%% Make sure that ebin/ exists and is on the path %% Make sure that ebin/ exists and is on the path
ok = filelib:ensure_dir(filename:join(OutDir, "dummy.beam")), ok = filelib:ensure_dir(filename:join(OutDir, "dummy.beam")),
CurrPath = code:get_path(),
true = code:add_path(filename:absname(OutDir)),
true = code:add_patha(filename:absname(OutDir)),
OutDir1 = proplists:get_value(outdir, ErlOpts, OutDir), OutDir1 = proplists:get_value(outdir, ErlOpts, OutDir),
G = init_erlcinfo(proplists:get_all_values(i, ErlOpts), AllErlFiles, Dir), G = init_erlcinfo(proplists:get_all_values(i, ErlOpts), AllErlFiles, Dir),
@ -161,7 +161,7 @@ doterl_compile(Config, Dir, OutDir, MoreSources, ErlOpts) ->
filename:extension(File) =:= ".erl"], filename:extension(File) =:= ".erl"],
NeededErlFiles = needed_files(G, ErlOpts, Dir, OutDir1, AllErlFiles), NeededErlFiles = needed_files(G, ErlOpts, Dir, OutDir1, AllErlFiles),
ErlFirstFiles = erl_first_files(Config, NeededErlFiles),
ErlFirstFiles = erl_first_files(Config, Dir, NeededErlFiles),
{DepErls, OtherErls} = lists:partition( {DepErls, OtherErls} = lists:partition(
fun(Source) -> digraph:in_degree(G, Source) > 0 end, fun(Source) -> digraph:in_degree(G, Source) > 0 end,
[File || File <- NeededErlFiles, not lists:member(File, ErlFirstFiles)]), [File || File <- NeededErlFiles, not lists:member(File, ErlFirstFiles)]),
@ -173,13 +173,13 @@ doterl_compile(Config, Dir, OutDir, MoreSources, ErlOpts) ->
fun(S, C) -> fun(S, C) ->
internal_erl_compile(C, Dir, S, OutDir1, ErlOpts) internal_erl_compile(C, Dir, S, OutDir1, ErlOpts)
end), end),
true = code:set_path(CurrPath),
ok. ok.
erl_first_files(Config, NeededErlFiles) ->
erl_first_files(Config, Dir, NeededErlFiles) ->
ErlFirstFilesConf = rebar_state:get(Config, erl_first_files, []), ErlFirstFilesConf = rebar_state:get(Config, erl_first_files, []),
%% NOTE: order of files in ErlFirstFiles is important! %% NOTE: order of files in ErlFirstFiles is important!
[File || File <- ErlFirstFilesConf, lists:member(File, NeededErlFiles)].
[filename:join(Dir, File) || File <- ErlFirstFilesConf,
lists:member(filename:join(Dir, File), NeededErlFiles)].
%% Get subset of SourceFiles which need to be recompiled, respecting %% Get subset of SourceFiles which need to be recompiled, respecting
%% dependencies induced by given graph G. %% dependencies induced by given graph G.
@ -541,9 +541,6 @@ maybe_expand_include_lib_path(File, Dir) ->
%% The use of -include_lib was probably incorrect by the user but lets try to make it work. %% The use of -include_lib was probably incorrect by the user but lets try to make it work.
%% We search in the outdir and outdir/../include to see if the header exists. %% We search in the outdir and outdir/../include to see if the header exists.
warn_and_find_path(File, Dir) -> warn_and_find_path(File, Dir) ->
?WARN("Bad use of -include_lib(\"~s\")."
" First path component should be the name of an application."
" You probably meant -include(\"~s\").", [File, File]),
SrcHeader = filename:join(Dir, File), SrcHeader = filename:join(Dir, File),
case filelib:is_regular(SrcHeader) of case filelib:is_regular(SrcHeader) of
true -> true ->
@ -555,7 +552,6 @@ warn_and_find_path(File, Dir) ->
true -> true ->
[filename:join(IncludeDir, File)]; [filename:join(IncludeDir, File)];
false -> false ->
?WARN("Could not find header for -include_lib(\"~s\").", [File]),
[] []
end end
end. end.

+ 0
- 5
src/rebar_otp_app.erl ファイルの表示

@ -120,10 +120,6 @@ preprocess(State, AppInfo, AppSrcFile) ->
AppFile = rebar_app_utils:app_src_to_app(OutDir, AppSrcFile), AppFile = rebar_app_utils:app_src_to_app(OutDir, AppSrcFile),
ok = rebar_file_utils:write_file_if_contents_differ(AppFile, Spec), ok = rebar_file_utils:write_file_if_contents_differ(AppFile, Spec),
%% Make certain that the ebin/ directory is available
%% on the code path
true = code:add_path(filename:absname(filename:dirname(AppFile))),
AppFile; AppFile;
{error, Reason} -> {error, Reason} ->
?PRV_ERROR({file_read, AppSrcFile, Reason}) ?PRV_ERROR({file_read, AppSrcFile, Reason})
@ -132,7 +128,6 @@ preprocess(State, AppInfo, AppSrcFile) ->
load_app_vars(State) -> load_app_vars(State) ->
case rebar_state:get(State, app_vars_file, undefined) of case rebar_state:get(State, app_vars_file, undefined) of
undefined -> undefined ->
?DEBUG("No app_vars_file defined.", []),
[]; [];
Filename -> Filename ->
?INFO("Loading app vars from ~p", [Filename]), ?INFO("Loading app vars from ~p", [Filename]),

+ 5
- 0
src/rebar_prv_common_test.erl ファイルの表示

@ -38,6 +38,8 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) -> do(State) ->
?INFO("Running Common Test suites...", []), ?INFO("Running Common Test suites...", []),
code:add_pathsa(rebar_state:code_paths(State, all_deps)),
%% Run ct provider prehooks %% Run ct provider prehooks
Providers = rebar_state:providers(State), Providers = rebar_state:providers(State),
Cwd = rebar_dir:get_cwd(), Cwd = rebar_dir:get_cwd(),
@ -47,11 +49,14 @@ do(State) ->
{ok, State1} = Result -> {ok, State1} = Result ->
%% Run ct provider posthooks %% Run ct provider posthooks
rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State1), rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State1),
rebar_utils:cleanup_code_path(rebar_state:code_paths(State1, default)),
Result; Result;
?PRV_ERROR(_) = Error -> ?PRV_ERROR(_) = Error ->
rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)),
Error Error
catch catch
throw:{error, Reason} -> throw:{error, Reason} ->
rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)),
?PRV_ERROR(Reason) ?PRV_ERROR(Reason)
end. end.

+ 14
- 10
src/rebar_prv_compile.erl ファイルの表示

@ -31,27 +31,33 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) -> do(State) ->
DepsPaths = rebar_state:code_paths(State, all_deps),
code:add_pathsa(DepsPaths),
ProjectApps = rebar_state:project_apps(State), ProjectApps = rebar_state:project_apps(State),
Providers = rebar_state:providers(State), Providers = rebar_state:providers(State),
Deps = rebar_state:deps_to_build(State), Deps = rebar_state:deps_to_build(State),
Cwd = rebar_dir:get_cwd(), Cwd = rebar_dir:get_cwd(),
rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
%% Need to allow global config vars used on deps %% Need to allow global config vars used on deps
%% Right now no way to differeniate and just give deps a new state %% Right now no way to differeniate and just give deps a new state
EmptyState = rebar_state:new(), EmptyState = rebar_state:new(),
build_apps(EmptyState, Providers, Deps), build_apps(EmptyState, Providers, Deps),
%% Use the project State for building project apps
%% Set hooks to empty so top-level hooks aren't run for each project app
State2 = rebar_state:set(rebar_state:set(State, post_hooks, []), pre_hooks, []),
{ok, ProjectApps1} = rebar_digraph:compile_order(ProjectApps), {ok, ProjectApps1} = rebar_digraph:compile_order(ProjectApps),
ProjectApps2 = build_apps(State2, Providers, ProjectApps1),
State3 = rebar_state:project_apps(State2, ProjectApps2),
%% Run top level hooks *before* project apps compiled but *after* deps are
rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
ProjectApps2 = build_apps(State, Providers, ProjectApps1),
State2 = rebar_state:project_apps(State, ProjectApps2),
ProjAppsPaths = [filename:join(rebar_app_info:out_dir(X), "ebin") || X <- ProjectApps2],
State3 = rebar_state:code_paths(State2, all_deps, DepsPaths ++ ProjAppsPaths),
rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State3),
rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State2),
rebar_utils:cleanup_code_path(rebar_state:code_paths(State3, default)),
{ok, State3}. {ok, State3}.
@ -77,12 +83,10 @@ build_app(State, Providers, AppInfo) ->
end, end,
%% Legacy hook support %% Legacy hook support
rebar_hooks:run_all_hooks(AppDir, pre, ?PROVIDER, Providers, S), rebar_hooks:run_all_hooks(AppDir, pre, ?PROVIDER, Providers, S),
AppInfo1 = compile(S, AppInfo), AppInfo1 = compile(S, AppInfo),
rebar_hooks:run_all_hooks(AppDir, post, ?PROVIDER, Providers, S), rebar_hooks:run_all_hooks(AppDir, post, ?PROVIDER, Providers, S),
true = code:add_patha(rebar_app_info:ebin_dir(AppInfo1)),
AppInfo1. AppInfo1.
compile(State, AppInfo) -> compile(State, AppInfo) ->

+ 1
- 1
src/rebar_prv_cover.erl ファイルの表示

@ -150,7 +150,7 @@ analysis(State, Task) ->
{Mod, process(Answer), File} {Mod, process(Answer), File}
end, end,
Mods), Mods),
true = code:set_path(OldPath),
true = rebar_utils:cleanup_code_path(OldPath),
Analysis. Analysis.
restore_cover_paths(State) -> restore_cover_paths(State) ->

+ 3
- 0
src/rebar_prv_dialyzer.erl ファイルの表示

@ -64,6 +64,7 @@ short_desc() ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) -> do(State) ->
?INFO("Dialyzer starting, this may take a while...", []), ?INFO("Dialyzer starting, this may take a while...", []),
code:add_pathsa(rebar_state:code_paths(State, all_deps)),
Plt = get_plt_location(State), Plt = get_plt_location(State),
Apps = rebar_state:project_apps(State), Apps = rebar_state:project_apps(State),
@ -74,6 +75,8 @@ do(State) ->
?PRV_ERROR({error_processing_apps, Error}); ?PRV_ERROR({error_processing_apps, Error});
throw:{dialyzer_warnings, Warnings} -> throw:{dialyzer_warnings, Warnings} ->
?PRV_ERROR({dialyzer_warnings, Warnings}) ?PRV_ERROR({dialyzer_warnings, Warnings})
after
rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default))
end. end.
-spec format_error(any()) -> iolist(). -spec format_error(any()) -> iolist().

+ 33
- 24
src/rebar_prv_erlydtl_compiler.erl ファイルの表示

@ -125,39 +125,48 @@ init(State) ->
do(State) -> do(State) ->
?INFO("Running erlydtl...", []), ?INFO("Running erlydtl...", []),
DtlOpts = proplists:unfold(rebar_state:get(State, erlydtl_opts, [])),
%% We need a project app to store the results under in _build
%% If there is more than 1 project app, check for an app config
%% if that doesn't exist, error out.
case rebar_state:project_apps(State) of
[App] ->
run_erlydtl(App, DtlOpts, State),
{ok, State};
Apps ->
case option(app, DtlOpts) of
undefined ->
?PRV_ERROR(no_main_app);
Name ->
run_erlydtl(rebar_app_utils:find(Name, Apps), DtlOpts, State),
{ok, State}
end
case rebar_state:get(State, escript_main_app, undefined) of
undefined ->
Dir = rebar_state:dir(State),
case rebar_app_discover:find_app(Dir, all) of
{true, AppInfo} ->
AllApps = rebar_state:project_apps(State) ++ rebar_state:all_deps(State),
case rebar_app_utils:find(rebar_app_info:name(AppInfo), AllApps) of
{ok, AppInfo1} ->
%% Use the existing app info instead of newly created one
run_erlydtl(AppInfo1, State);
_ ->
run_erlydtl(AppInfo, State)
end,
{ok, State};
_ ->
?PRV_ERROR(no_main_app)
end;
Name ->
AllApps = rebar_state:project_apps(State) ++ rebar_state:all_deps(State),
{ok, App} = rebar_app_utils:find(Name, AllApps),
run_erlydtl(App, State),
{ok, State}
end. end.
run_erlydtl(App, DtlOpts, State) ->
Dir = rebar_app_info:dir(App),
run_erlydtl(App, State) ->
Dir = rebar_state:dir(State),
DtlOpts = proplists:unfold(rebar_state:get(State, erlydtl_opts, [])),
TemplateDir = filename:join(Dir, option(doc_root, DtlOpts)),
DtlOpts2 = [{doc_root, TemplateDir} | proplists:delete(doc_root, DtlOpts)],
OutDir = rebar_app_info:ebin_dir(App), OutDir = rebar_app_info:ebin_dir(App),
filelib:ensure_dir(filename:join(OutDir, "dummy.beam")),
rebar_base_compiler:run(State, rebar_base_compiler:run(State,
[], [],
filename:join(Dir, option(doc_root, DtlOpts)),
option(source_ext, DtlOpts),
TemplateDir,
option(source_ext, DtlOpts2),
OutDir, OutDir,
option(module_ext, DtlOpts) ++ ".beam",
option(module_ext, DtlOpts2) ++ ".beam",
fun(S, T, C) -> fun(S, T, C) ->
compile_dtl(C, S, T, DtlOpts, Dir, OutDir)
compile_dtl(C, S, T, DtlOpts2, Dir, OutDir)
end, end,
[{check_last_mod, false}, [{check_last_mod, false},
{recursive, option(recursive, DtlOpts)}]).
{recursive, option(recursive, DtlOpts2)}]).
-spec format_error(any()) -> iolist(). -spec format_error(any()) -> iolist().
format_error(no_main_app) -> format_error(no_main_app) ->

+ 37
- 25
src/rebar_prv_escriptize.erl ファイルの表示

@ -62,17 +62,18 @@ desc() ->
do(State) -> do(State) ->
?INFO("Building escript...", []), ?INFO("Building escript...", []),
case rebar_state:project_apps(State) of
[App] ->
escriptize(State, App);
Apps ->
case rebar_state:get(State, escript_main_app, undefined) of
undefined ->
?PRV_ERROR(no_main_app);
Name ->
AppInfo = rebar_app_utils:find(Name, Apps),
escriptize(State, AppInfo)
end
case rebar_state:get(State, escript_main_app, undefined) of
undefined ->
case rebar_state:project_apps(State) of
[App] ->
escriptize(State, App);
_ ->
?PRV_ERROR(no_main_app)
end;
Name ->
AllApps = rebar_state:all_deps(State)++rebar_state:project_apps(State),
AppInfo = rebar_app_utils:find(Name, AllApps),
escriptize(State, AppInfo)
end. end.
escriptize(State0, App) -> escriptize(State0, App) ->
@ -89,8 +90,9 @@ escriptize(State0, App) ->
%% in the output file. We then use the .app files for each of these %% in the output file. We then use the .app files for each of these
%% to pull in all the .beam files. %% to pull in all the .beam files.
InclApps = lists:usort(rebar_state:get(State, escript_incl_apps, []) InclApps = lists:usort(rebar_state:get(State, escript_incl_apps, [])
++ all_deps(State)),
InclBeams = get_app_beams(InclApps),
++ all_deps(State)),
AllApps = rebar_state:all_deps(State)++rebar_state:project_apps(State),
InclBeams = get_apps_beams(InclApps, AllApps),
%% Look for a list of extra files to include in the output file. %% Look for a list of extra files to include in the output file.
%% For internal rebar-private use only. Do not use outside rebar. %% For internal rebar-private use only. Do not use outside rebar.
@ -139,22 +141,32 @@ format_error(no_main_app) ->
%% Internal functions %% Internal functions
%% =================================================================== %% ===================================================================
get_app_beams(Apps) ->
get_app_beams(Apps, []).
get_apps_beams(Apps, AllApps) ->
get_apps_beams(Apps, AllApps, []).
get_app_beams([], Acc) ->
get_apps_beams([], _, Acc) ->
Acc; Acc;
get_app_beams([App | Rest], Acc) ->
case code:lib_dir(App, ebin) of
{error, bad_name} ->
throw(?PRV_ERROR({bad_name, App}));
Path ->
Prefix = filename:join(atom_to_list(App), "ebin"),
Acc2 = load_files(Prefix, "*.beam", Path),
Acc3 = load_files(Prefix, "*.app", Path),
get_app_beams(Rest, Acc3 ++ Acc2 ++ Acc)
get_apps_beams([App | Rest], AllApps, Acc) ->
case rebar_app_utils:find(ec_cnv:to_binary(App), AllApps) of
{ok, App1} ->
OutDir = filename:absname(rebar_app_info:ebin_dir(App1)),
Beams = get_app_beams(App, OutDir),
get_apps_beams(Rest, AllApps, Beams ++ Acc);
_->
case code:lib_dir(App, ebin) of
{error, bad_name} ->
throw(?PRV_ERROR({bad_name, App}));
Path ->
Beams = get_app_beams(App, Path),
get_apps_beams(Rest, AllApps, Beams ++ Acc)
end
end. end.
get_app_beams(App, Path) ->
Prefix = filename:join(atom_to_list(App), "ebin"),
load_files(Prefix, "*.beam", Path) ++
load_files(Prefix, "*.app", Path).
get_extra(State) -> get_extra(State) ->
Extra = rebar_state:get(State, escript_incl_extra, []), Extra = rebar_state:get(State, escript_incl_extra, []),
lists:foldl(fun({Wildcard, Dir}, Files) -> lists:foldl(fun({Wildcard, Dir}, Files) ->

+ 4
- 0
src/rebar_prv_eunit.erl ファイルの表示

@ -37,6 +37,7 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) -> do(State) ->
?INFO("Performing EUnit tests...", []), ?INFO("Performing EUnit tests...", []),
code:add_pathsa(rebar_state:code_paths(State, all_deps)),
%% Run eunit provider prehooks %% Run eunit provider prehooks
Providers = rebar_state:providers(State), Providers = rebar_state:providers(State),
Cwd = rebar_dir:get_cwd(), Cwd = rebar_dir:get_cwd(),
@ -48,11 +49,14 @@ do(State) ->
{ok, State1} -> {ok, State1} ->
%% Run eunit provider posthooks %% Run eunit provider posthooks
rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State1), rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State1),
rebar_utils:cleanup_code_path(rebar_state:code_paths(State1, default)),
{ok, State1}; {ok, State1};
Error -> Error ->
rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)),
Error Error
end; end;
Error -> Error ->
rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)),
Error Error
end. end.

+ 102
- 52
src/rebar_prv_install_deps.erl ファイルの表示

@ -82,13 +82,9 @@ do(State) ->
?PRV_ERROR({cycles, Cycles}); ?PRV_ERROR({cycles, Cycles});
{error, Error} -> {error, Error} ->
{error, Error}; {error, Error};
no_cycle ->
case compile_order(Source, ProjectApps) of
{ok, ToCompile} ->
{ok, rebar_state:deps_to_build(State1, ToCompile)};
{error, Error} ->
{error, Error}
end
{no_cycle, Sorted} ->
ToCompile = cull_compile(Sorted, ProjectApps),
{ok, rebar_state:deps_to_build(State1, ToCompile)}
end end
catch catch
%% maybe_fetch will maybe_throw an exception to break out of some loops %% maybe_fetch will maybe_throw an exception to break out of some loops
@ -132,30 +128,39 @@ handle_deps(Profile, State, Deps, Locks) when is_list(Locks) ->
handle_deps(_Profile, State, [], _, _) -> handle_deps(_Profile, State, [], _, _) ->
{ok, [], State}; {ok, [], State};
handle_deps(Profile, State0, Deps, Upgrade, Locks) -> handle_deps(Profile, State0, Deps, Upgrade, Locks) ->
%% Read in package index and dep graph
{Packages, Graph} = rebar_state:packages(State0),
Registry = rebar_packages:registry(State0),
State = rebar_state:packages(rebar_state:registry(State0, Registry), {Packages, Graph}),
%% Split source deps from pkg deps, needed to keep backwards compatibility %% Split source deps from pkg deps, needed to keep backwards compatibility
DepsDir = rebar_dir:deps_dir(State),
{SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, State, Locks, 0),
DepsDir = profile_dep_dir(State0, Profile),
{SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, State0, Locks, 0),
%% Fetch transitive src deps %% Fetch transitive src deps
{State1, SrcApps, PkgDeps1, Seen} =
update_src_deps(Profile, 0, SrcDeps, PkgDeps, [], State, Upgrade, sets:new(), Locks),
{State1, SrcApps, PkgDeps1, Seen} = update_src_deps(Profile, 0, SrcDeps, PkgDeps, []
,State0, Upgrade, sets:new(), Locks),
{Solved, State2} =
update_pkg_deps(Profile, Packages, PkgDeps1, Graph, Upgrade, Seen, State1),
{Solved, State4} =
case PkgDeps1 of
[] ->
{[], State1};
_ ->
%% Read in package index and dep graph
{Packages, Graph} = rebar_state:packages(State1),
Registry = rebar_packages:registry(State1),
State2 = rebar_state:packages(rebar_state:registry(State1, Registry)
,{Packages, Graph}),
update_pkg_deps(Profile, Packages, PkgDeps1
,Graph, Upgrade, Seen, State2)
end,
AllDeps = lists:ukeymerge(2 AllDeps = lists:ukeymerge(2
,lists:ukeysort(2, SrcApps) ,lists:ukeysort(2, SrcApps)
,lists:ukeysort(2, Solved)), ,lists:ukeysort(2, Solved)),
%% Sort all apps to build order
State3 = rebar_state:all_deps(State2, AllDeps),
State5 = rebar_state:update_all_deps(State4, AllDeps),
CodePaths = [rebar_app_info:ebin_dir(A) || A <- AllDeps], CodePaths = [rebar_app_info:ebin_dir(A) || A <- AllDeps],
ok = code:add_pathsa(CodePaths),
State6 = rebar_state:update_code_paths(State5, all_deps, CodePaths),
{ok, AllDeps, State3}.
{ok, AllDeps, State6}.
%% =================================================================== %% ===================================================================
%% Internal functions %% Internal functions
@ -171,17 +176,11 @@ find_cycles(Apps) ->
case rebar_digraph:compile_order(Apps) of case rebar_digraph:compile_order(Apps) of
{error, {cycles, Cycles}} -> {cycles, Cycles}; {error, {cycles, Cycles}} -> {cycles, Cycles};
{error, Error} -> {error, Error}; {error, Error} -> {error, Error};
{ok, _} -> no_cycle
{ok, Sorted} -> {no_cycle, Sorted}
end. end.
compile_order(Source, ProjectApps) ->
case rebar_digraph:compile_order(Source) of
{ok, Sort} ->
%% Valid apps are compiled and good
{ok, lists:dropwhile(fun not_needs_compile/1, Sort -- ProjectApps)};
{error, Error} ->
{error, Error}
end.
cull_compile(TopSortedDeps, ProjectApps) ->
lists:dropwhile(fun not_needs_compile/1, TopSortedDeps -- ProjectApps).
update_pkg_deps(Profile, Packages, PkgDeps, Graph, Upgrade, Seen, State) -> update_pkg_deps(Profile, Packages, PkgDeps, Graph, Upgrade, Seen, State) ->
case PkgDeps of case PkgDeps of
@ -203,7 +202,7 @@ update_pkg_deps(Profile, Packages, PkgDeps, Graph, Upgrade, Seen, State) ->
update_pkg_deps(Profile, Pkgs, Packages, Upgrade, Seen, State) -> update_pkg_deps(Profile, Pkgs, Packages, Upgrade, Seen, State) ->
%% Create app_info record for each pkg dep %% Create app_info record for each pkg dep
DepsDir = rebar_dir:deps_dir(State),
DepsDir = profile_dep_dir(State, Profile),
{Solved, _, State1} {Solved, _, State1}
= lists:foldl(fun(Pkg, {Acc, SeenAcc, StateAcc}) -> = lists:foldl(fun(Pkg, {Acc, SeenAcc, StateAcc}) ->
handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Acc, SeenAcc, StateAcc) handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Acc, SeenAcc, StateAcc)
@ -214,7 +213,7 @@ handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Fetched, Seen, State) -
AppInfo = package_to_app(DepsDir, Packages, Pkg), AppInfo = package_to_app(DepsDir, Packages, Pkg),
Level = rebar_app_info:dep_level(AppInfo), Level = rebar_app_info:dep_level(AppInfo),
{NewSeen, NewState} = maybe_lock(Profile, AppInfo, Seen, State, Level), {NewSeen, NewState} = maybe_lock(Profile, AppInfo, Seen, State, Level),
{_, AppInfo1} = maybe_fetch(AppInfo, Upgrade, Seen, NewState),
{_, AppInfo1} = maybe_fetch(AppInfo, Profile, Upgrade, Seen, NewState),
{[AppInfo1 | Fetched], NewSeen, NewState}. {[AppInfo1 | Fetched], NewSeen, NewState}.
maybe_lock(Profile, AppInfo, Seen, State, Level) -> maybe_lock(Profile, AppInfo, Seen, State, Level) ->
@ -252,7 +251,7 @@ package_to_app(DepsDir, Packages, {Name, Vsn, Level}) ->
|| {PkgName,PkgVsn} <- proplists:get_value(<<"deps">>, P, [])], || {PkgName,PkgVsn} <- proplists:get_value(<<"deps">>, P, [])],
{ok, AppInfo} = rebar_app_info:new(Name, Vsn), {ok, AppInfo} = rebar_app_info:new(Name, Vsn),
AppInfo1 = rebar_app_info:deps(AppInfo, PkgDeps), AppInfo1 = rebar_app_info:deps(AppInfo, PkgDeps),
AppInfo2 = rebar_app_info:dir(AppInfo1, rebar_dir:deps_dir(DepsDir, Name)),
AppInfo2 = rebar_app_info:dir(AppInfo1, filename:join([DepsDir, Name])),
AppInfo3 = rebar_app_info:dep_level(AppInfo2, Level), AppInfo3 = rebar_app_info:dep_level(AppInfo2, Level),
rebar_app_info:source(AppInfo3, {pkg, Name, Vsn}) rebar_app_info:source(AppInfo3, {pkg, Name, Vsn})
end. end.
@ -278,7 +277,7 @@ update_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrad
Name = rebar_app_info:name(AppInfo), Name = rebar_app_info:name(AppInfo),
case sets:is_element(Name, Seen) of case sets:is_element(Name, Seen) of
true -> true ->
update_seen_src_dep(AppInfo, Level,
update_seen_src_dep(AppInfo, Profile, Level,
SrcDeps, PkgDeps, SrcApps, SrcDeps, PkgDeps, SrcApps,
State, Upgrade, Seen, BaseLocks, Locks); State, Upgrade, Seen, BaseLocks, Locks);
false -> false ->
@ -288,7 +287,13 @@ update_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrad
end. end.
update_seen_src_dep(AppInfo, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, BaseLocks, Locks) ->
profile_dep_dir(State, Profile) ->
case Profile of
default -> filename:join([rebar_dir:profile_dir(State, [default]), rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR)]);
_ -> rebar_dir:deps_dir(State)
end.
update_seen_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, BaseLocks, Locks) ->
Name = rebar_app_info:name(AppInfo), Name = rebar_app_info:name(AppInfo),
%% If seen from lock file don't print warning about skipping %% If seen from lock file don't print warning about skipping
case lists:keymember(Name, 1, BaseLocks) of case lists:keymember(Name, 1, BaseLocks) of
@ -303,7 +308,7 @@ update_seen_src_dep(AppInfo, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, S
{SrcDeps, PkgDeps, SrcApps, State, Seen, Locks}; {SrcDeps, PkgDeps, SrcApps, State, Seen, Locks};
true -> true ->
{NewSrcDeps, NewPkgDeps, NewSrcApps, NewState, NewLocks} {NewSrcDeps, NewPkgDeps, NewSrcApps, NewState, NewLocks}
= handle_dep(AppInfo, SrcDeps, PkgDeps, SrcApps,
= handle_dep(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps,
Level, State, Locks), Level, State, Locks),
{NewSrcDeps, NewPkgDeps, NewSrcApps, NewState, Seen, NewLocks} {NewSrcDeps, NewPkgDeps, NewSrcApps, NewState, Seen, NewLocks}
end. end.
@ -313,22 +318,22 @@ update_unseen_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State,
{NewSrcDeps, NewPkgDeps, NewSrcApps, State2, NewLocks} {NewSrcDeps, NewPkgDeps, NewSrcApps, State2, NewLocks}
= case Upgrade of = case Upgrade of
true -> true ->
handle_upgrade(AppInfo, SrcDeps, PkgDeps, SrcApps,
handle_upgrade(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps,
Level, State1, Locks); Level, State1, Locks);
_ -> _ ->
{_, AppInfo1} = maybe_fetch(AppInfo, false, Seen, State1),
handle_dep(AppInfo1, SrcDeps, PkgDeps, SrcApps,
{_, AppInfo1} = maybe_fetch(AppInfo, Profile, false, Seen, State1),
handle_dep(AppInfo1, Profile, SrcDeps, PkgDeps, SrcApps,
Level, State1, Locks) Level, State1, Locks)
end, end,
{NewSrcDeps, NewPkgDeps, NewSrcApps, State2, NewSeen, NewLocks}. {NewSrcDeps, NewPkgDeps, NewSrcApps, State2, NewSeen, NewLocks}.
handle_upgrade(AppInfo, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
handle_upgrade(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
Name = rebar_app_info:name(AppInfo), Name = rebar_app_info:name(AppInfo),
case lists:keyfind(Name, 1, Locks) of case lists:keyfind(Name, 1, Locks) of
false -> false ->
case maybe_fetch(AppInfo, true, sets:new(), State) of
case maybe_fetch(AppInfo, Profile, true, sets:new(), State) of
{true, AppInfo1} -> {true, AppInfo1} ->
handle_dep(AppInfo1, SrcDeps, PkgDeps, SrcApps,
handle_dep(AppInfo1, Profile, SrcDeps, PkgDeps, SrcApps,
Level, State, Locks); Level, State, Locks);
{false, AppInfo1} -> {false, AppInfo1} ->
@ -338,8 +343,8 @@ handle_upgrade(AppInfo, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
{[AppInfo|SrcDeps], PkgDeps, SrcApps, State, Locks} {[AppInfo|SrcDeps], PkgDeps, SrcApps, State, Locks}
end. end.
handle_dep(AppInfo, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
DepsDir = rebar_dir:deps_dir(State),
handle_dep(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
DepsDir = profile_dep_dir(State, Profile),
{AppInfo1, NewSrcDeps, NewPkgDeps, NewLocks, State1} = {AppInfo1, NewSrcDeps, NewPkgDeps, NewLocks, State1} =
handle_dep(State, DepsDir, AppInfo, Locks, Level), handle_dep(State, DepsDir, AppInfo, Locks, Level),
AppInfo2 = rebar_app_info:dep_level(AppInfo1, Level), AppInfo2 = rebar_app_info:dep_level(AppInfo1, Level),
@ -374,9 +379,9 @@ handle_dep(State, DepsDir, AppInfo, Locks, Level) ->
{SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, S3, Locks, Level), {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, S3, Locks, Level),
{AppInfo2, SrcDeps, PkgDeps, Locks++NewLocks, State1}. {AppInfo2, SrcDeps, PkgDeps, Locks++NewLocks, State1}.
-spec maybe_fetch(rebar_app_info:t(), boolean() | {true, binary(), integer()},
-spec maybe_fetch(rebar_app_info:t(), atom(), boolean() | {true, binary(), integer()},
sets:set(binary()), rebar_state:t()) -> {boolean(), rebar_app_info:t()}. sets:set(binary()), rebar_state:t()) -> {boolean(), rebar_app_info:t()}.
maybe_fetch(AppInfo, Upgrade, Seen, State) ->
maybe_fetch(AppInfo, Profile, Upgrade, Seen, State) ->
AppDir = ec_cnv:to_list(rebar_app_info:dir(AppInfo)), AppDir = ec_cnv:to_list(rebar_app_info:dir(AppInfo)),
%% Don't fetch dep if it exists in the _checkouts dir %% Don't fetch dep if it exists in the _checkouts dir
case rebar_app_info:is_checkout(AppInfo) of case rebar_app_info:is_checkout(AppInfo) of
@ -385,22 +390,27 @@ maybe_fetch(AppInfo, Upgrade, Seen, State) ->
false -> false ->
case rebar_app_discover:find_app(AppDir, all) of case rebar_app_discover:find_app(AppDir, all) of
false -> false ->
case in_default(AppInfo, State) of
case already_in_default(AppInfo, State) of
false -> false ->
{fetch_app(AppInfo, AppDir, State), AppInfo};
case fetch_app(AppInfo, AppDir, State) of
true ->
maybe_symlink_default(State, Profile, AppDir, AppInfo),
{true, update_app_info(AppInfo)};
Other ->
{Other, AppInfo}
end;
{true, FoundApp} -> {true, FoundApp} ->
%% Preserve the state we created with overrides %% Preserve the state we created with overrides
AppState = rebar_app_info:state(AppInfo), AppState = rebar_app_info:state(AppInfo),
FoundApp1 = rebar_app_info:state(FoundApp, AppState), FoundApp1 = rebar_app_info:state(FoundApp, AppState),
?INFO("Linking ~s to ~s", [rebar_app_info:dir(FoundApp1), AppDir]),
filelib:ensure_dir(AppDir),
rebar_file_utils:symlink_or_copy(rebar_app_info:dir(FoundApp1), AppDir),
symlink_dep(rebar_app_info:dir(FoundApp1), AppDir),
{true, FoundApp1} {true, FoundApp1}
end; end;
{true, AppInfo1} -> {true, AppInfo1} ->
%% Preserve the state we created with overrides %% Preserve the state we created with overrides
AppState = rebar_app_info:state(AppInfo), AppState = rebar_app_info:state(AppInfo),
AppInfo2 = rebar_app_info:state(AppInfo1, AppState), AppInfo2 = rebar_app_info:state(AppInfo1, AppState),
maybe_symlink_default(State, Profile, AppDir, AppInfo2),
case sets:is_element(rebar_app_info:name(AppInfo), Seen) of case sets:is_element(rebar_app_info:name(AppInfo), Seen) of
true -> true ->
{false, AppInfo2}; {false, AppInfo2};
@ -410,11 +420,42 @@ maybe_fetch(AppInfo, Upgrade, Seen, State) ->
end end
end. end.
in_default(AppInfo, State) ->
already_in_default(AppInfo, State) ->
Name = ec_cnv:to_list(rebar_app_info:name(AppInfo)), Name = ec_cnv:to_list(rebar_app_info:name(AppInfo)),
DefaultAppDir = filename:join([rebar_state:get(State, base_dir), "default", "lib", Name]), DefaultAppDir = filename:join([rebar_state:get(State, base_dir), "default", "lib", Name]),
rebar_app_discover:find_app(DefaultAppDir, all). rebar_app_discover:find_app(DefaultAppDir, all).
needs_symlinking(State, Profile) ->
case {rebar_state:current_profiles(State), Profile} of
{[default], default} ->
%% file will be in default already -- this is the only run we have
false;
{_, default} ->
%% file fetched to default, needs to be linked to the current
%% run's directory.
true;
_ ->
%% File fetched to the right directory already
false
end.
maybe_symlink_default(State, Profile, AppDir, AppInfo) ->
case needs_symlinking(State, Profile) of
true ->
SymDir = filename:join([rebar_dir:deps_dir(State),
rebar_app_info:name(AppInfo)]),
symlink_dep(AppDir, SymDir),
true;
false ->
false
end.
symlink_dep(From, To) ->
?INFO("Linking ~s to ~s", [From, To]),
filelib:ensure_dir(To),
rebar_file_utils:symlink_or_copy(From, To).
-spec parse_deps(binary(), list(), rebar_state:t(), list(), integer()) -> {[rebar_app_info:t()], [pkg_dep()]}. -spec parse_deps(binary(), list(), rebar_state:t(), list(), integer()) -> {[rebar_app_info:t()], [pkg_dep()]}.
parse_deps(DepsDir, Deps, State, Locks, Level) -> parse_deps(DepsDir, Deps, State, Locks, Level) ->
lists:foldl(fun(Dep, Acc) -> lists:foldl(fun(Dep, Acc) ->
@ -521,6 +562,15 @@ fetch_app(AppInfo, AppDir, State) ->
Result Result
end. end.
update_app_info(AppInfo) ->
AppDetails = rebar_app_info:app_details(AppInfo),
Applications = proplists:get_value(applications, AppDetails, []),
IncludedApplications = proplists:get_value(included_applications, AppDetails, []),
AppInfo1 = rebar_app_info:applications(
rebar_app_info:app_details(AppInfo, AppDetails),
IncludedApplications++Applications),
rebar_app_info:valid(AppInfo1, false).
maybe_upgrade(AppInfo, AppDir, false, State) -> maybe_upgrade(AppInfo, AppDir, false, State) ->
Source = rebar_app_info:source(AppInfo), Source = rebar_app_info:source(AppInfo),
rebar_fetch:needs_update(AppDir, Source, State); rebar_fetch:needs_update(AppDir, Source, State);

+ 16
- 15
src/rebar_prv_lock.erl ファイルの表示

@ -23,30 +23,31 @@ init(State) ->
{deps, ?DEPS}, {deps, ?DEPS},
{example, ""}, {example, ""},
{short_desc, "Locks dependencies."}, {short_desc, "Locks dependencies."},
{desc, info("Locks dependencies")},
{desc, "Locks dependencies"},
{opts, []}])), {opts, []}])),
{ok, State1}. {ok, State1}.
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) -> do(State) ->
AllDeps = rebar_state:lock(State),
Locks = [begin
Dir = rebar_app_info:dir(Dep),
Source = rebar_app_info:source(Dep),
%% If source is tuple it is a source dep
%% e.g. {git, "git://github.com/ninenines/cowboy.git", "master"}
{rebar_app_info:name(Dep)
,rebar_fetch:lock_source(Dir, Source, State)
,rebar_app_info:dep_level(Dep)}
end || Dep <- AllDeps, not(rebar_app_info:is_checkout(Dep))],
Locks = build_locks(State),
Dir = rebar_state:dir(State), Dir = rebar_state:dir(State),
file:write_file(filename:join(Dir, ?LOCK_FILE), io_lib:format("~p.~n", [Locks])),
file:write_file(filename:join(Dir, ?LOCK_FILE),
io_lib:format("~p.~n", [Locks])),
{ok, State}. {ok, State}.
-spec format_error(any()) -> iolist(). -spec format_error(any()) -> iolist().
format_error(Reason) -> format_error(Reason) ->
io_lib:format("~p", [Reason]). io_lib:format("~p", [Reason]).
info(_) ->
"".
build_locks(State) ->
AllDeps = rebar_state:lock(State),
[begin
Dir = rebar_app_info:dir(Dep),
Source = rebar_app_info:source(Dep),
%% If source is tuple it is a source dep
%% e.g. {git, "git://github.com/ninenines/cowboy.git", "master"}
{rebar_app_info:name(Dep)
,rebar_fetch:lock_source(Dir, Source, State)
,rebar_app_info:dep_level(Dep)}
end || Dep <- AllDeps, not(rebar_app_info:is_checkout(Dep))].

+ 2
- 1
src/rebar_prv_release.erl ファイルの表示

@ -35,8 +35,9 @@ do(State) ->
Caller = rebar_state:get(State, caller, api), Caller = rebar_state:get(State, caller, api),
Options = rebar_state:command_args(State), Options = rebar_state:command_args(State),
DepsDir = rebar_dir:deps_dir(State), DepsDir = rebar_dir:deps_dir(State),
ProjectAppDirs = lists:delete(".", ?DEFAULT_PROJECT_APP_DIRS),
LibDirs = rebar_utils:filtermap(fun ec_file:exists/1, LibDirs = rebar_utils:filtermap(fun ec_file:exists/1,
[DepsDir | lists:delete(".", ?DEFAULT_PROJECT_APP_DIRS)]),
[?DEFAULT_CHECKOUTS_DIR, DepsDir | ProjectAppDirs]),
OutputDir = filename:join(rebar_dir:base_dir(State), ?DEFAULT_RELEASE_DIR), OutputDir = filename:join(rebar_dir:base_dir(State), ?DEFAULT_RELEASE_DIR),
AllOptions = string:join(["release" | Options], " "), AllOptions = string:join(["release" | Options], " "),
try try

+ 7
- 6
src/rebar_prv_shell.erl ファイルの表示

@ -92,7 +92,9 @@ shell(State) ->
%% times). removes at most the error_logger added by init and the %% times). removes at most the error_logger added by init and the
%% error_logger added by the tty handler %% error_logger added by the tty handler
ok = remove_error_handler(3), ok = remove_error_handler(3),
%% add test paths
%% Add deps to path
code:add_pathsa(rebar_state:code_paths(State, all_deps)),
%% add project app test paths
ok = add_test_paths(State), ok = add_test_paths(State),
%% this call never returns (until user quits shell) %% this call never returns (until user quits shell)
timer:sleep(infinity). timer:sleep(infinity).
@ -121,10 +123,9 @@ wait_until_user_started(Timeout) ->
add_test_paths(State) -> add_test_paths(State) ->
lists:foreach(fun(App) -> lists:foreach(fun(App) ->
AppDir = rebar_app_info:out_dir(App),
%% ignore errors resulting from non-existent directories
_ = code:add_path(filename:join([AppDir, "ebin"])),
_ = code:add_path(filename:join([AppDir, "test"]))
end, rebar_state:project_apps(State)),
AppDir = rebar_app_info:out_dir(App),
%% ignore errors resulting from non-existent directories
_ = code:add_path(filename:join([AppDir, "test"]))
end, rebar_state:project_apps(State)),
_ = code:add_path(filename:join([rebar_dir:base_dir(State), "test"])), _ = code:add_path(filename:join([rebar_dir:base_dir(State), "test"])),
ok. ok.

+ 2
- 1
src/rebar_prv_tar.erl ファイルの表示

@ -35,8 +35,9 @@ do(State) ->
Caller = rebar_state:get(State, caller, api), Caller = rebar_state:get(State, caller, api),
Options = rebar_state:command_args(State), Options = rebar_state:command_args(State),
DepsDir = rebar_dir:deps_dir(State), DepsDir = rebar_dir:deps_dir(State),
ProjectAppDirs = lists:delete(".", ?DEFAULT_PROJECT_APP_DIRS),
LibDirs = rebar_utils:filtermap(fun ec_file:exists/1, LibDirs = rebar_utils:filtermap(fun ec_file:exists/1,
[DepsDir | lists:delete(".", ?DEFAULT_PROJECT_APP_DIRS)]),
[?DEFAULT_CHECKOUTS_DIR, DepsDir | ProjectAppDirs]),
OutputDir = filename:join(rebar_dir:base_dir(State), ?DEFAULT_RELEASE_DIR), OutputDir = filename:join(rebar_dir:base_dir(State), ?DEFAULT_RELEASE_DIR),
AllOptions = string:join(["release", "tar" | Options], " "), AllOptions = string:join(["release", "tar" | Options], " "),
case rebar_state:get(State, relx, []) of case rebar_state:get(State, relx, []) of

+ 84
- 0
src/rebar_prv_unlock.erl ファイルの表示

@ -0,0 +1,84 @@
-module(rebar_prv_unlock).
-behaviour(provider).
-export([init/1,
do/1,
format_error/1]).
-include("rebar.hrl").
-include_lib("providers/include/providers.hrl").
-define(PROVIDER, unlock).
-define(DEPS, []).
%% ===================================================================
%% Public API
%% ===================================================================
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
State1 = rebar_state:add_provider(
State,
providers:create([{name, ?PROVIDER},
{module, ?MODULE},
{bare, false},
{deps, ?DEPS},
{example, ""},
{short_desc, "Unlock dependencies."},
{desc, "Unlock project dependencies. Mentioning no application "
"will unlock all dependencies. To unlock specific dependencies, "
"their name can be listed in the command."},
{opts, [
{package, undefined, undefined, string,
"List of packages to upgrade. If not specified, all dependencies are upgraded."}
]}
])
),
{ok, State1}.
do(State) ->
Dir = rebar_state:dir(State),
LockFile = filename:join(Dir, ?LOCK_FILE),
case file:consult(LockFile) of
{error, enoent} ->
%% Our work is done.
{ok, State};
{error, Reason} ->
?PRV_ERROR({file,Reason});
{ok, [Locks]} ->
case handle_unlocks(State, Locks, LockFile) of
ok ->
{ok, State};
{error, Reason} ->
?PRV_ERROR({file,Reason})
end;
{ok, _Other} ->
?PRV_ERROR(unknown_lock_format)
end.
-spec format_error(any()) -> iolist().
format_error({file, Reason}) ->
io_lib:format("Lock file editing failed for reason ~p", [Reason]);
format_error(unknown_lock_format) ->
"Lock file format unknown";
format_error(Reason) ->
io_lib:format("~p", [Reason]).
handle_unlocks(State, Locks, LockFile) ->
{Args, _} = rebar_state:command_parsed_args(State),
Names = parse_names(ec_cnv:to_binary(proplists:get_value(package, Args, <<"">>))),
case [Lock || Lock = {Name, _, _} <- Locks, not lists:member(Name, Names)] of
[] ->
file:delete(LockFile);
_ when Names =:= [] -> % implicitly all locks
file:delete(LockFile);
NewLocks ->
file:write_file(LockFile, io_lib:format("~p.~n", [NewLocks]))
end.
parse_names(Bin) ->
case lists:usort(re:split(Bin, <<" *, *">>, [trim])) of
[<<"">>] -> []; % nothing submitted
Other -> Other
end.

+ 4
- 2
src/rebar_prv_update.erl ファイルの表示

@ -91,7 +91,7 @@ hex_to_graph(Filename) ->
{Dict1, Graph}. {Dict1, Graph}.
update_graph(Pkg, PkgVsn, Deps, HexRegistry, Graph) -> update_graph(Pkg, PkgVsn, Deps, HexRegistry, Graph) ->
lists:foldl(fun([Dep, DepVsn, _, _], DepsListAcc) ->
lists:foldl(fun([Dep, DepVsn, false, _AppName | _], DepsListAcc) ->
case DepVsn of case DepVsn of
<<"~> ", Vsn/binary>> -> <<"~> ", Vsn/binary>> ->
HighestDepVsn = rebar_packages:find_highest_matching(Dep, Vsn, HexRegistry), HighestDepVsn = rebar_packages:find_highest_matching(Dep, Vsn, HexRegistry),
@ -100,5 +100,7 @@ update_graph(Pkg, PkgVsn, Deps, HexRegistry, Graph) ->
Vsn -> Vsn ->
digraph:add_edge(Graph, {Pkg, PkgVsn}, {Dep, Vsn}), digraph:add_edge(Graph, {Pkg, PkgVsn}, {Dep, Vsn}),
[{Dep, Vsn} | DepsListAcc] [{Dep, Vsn} | DepsListAcc]
end
end;
([_Dep, _DepVsn, true, _AppName | _], DepsListAcc) ->
DepsListAcc
end, [], Deps). end, [], Deps).

+ 20
- 11
src/rebar_prv_upgrade.erl ファイルの表示

@ -91,29 +91,38 @@ parse_names(Bin, Locks) ->
prepare_locks([], _, Locks, Unlocks) -> prepare_locks([], _, Locks, Unlocks) ->
{Locks, Unlocks}; {Locks, Unlocks};
prepare_locks([Name|Names], Deps, Locks, Unlocks) -> prepare_locks([Name|Names], Deps, Locks, Unlocks) ->
AtomName = binary_to_atom(Name, utf8),
case lists:keyfind(Name, 1, Locks) of case lists:keyfind(Name, 1, Locks) of
{_, _, 0} = Lock -> {_, _, 0} = Lock ->
AtomName = binary_to_atom(Name, utf8),
case lists:keyfind(AtomName, 1, Deps) of case lists:keyfind(AtomName, 1, Deps) of
false -> false ->
?PRV_ERROR({unknown_dependency, Name}); ?PRV_ERROR({unknown_dependency, Name});
Dep -> Dep ->
Source = case Dep of
{_, Src} -> Src;
{_, _, Src} -> Src
end,
{NewLocks, NewUnlocks} = unlock_higher_than(0, Locks -- [Lock]),
prepare_locks(Names,
Deps,
NewLocks,
{Source, NewLocks, NewUnlocks} = prepare_lock(Dep, Lock, Locks),
prepare_locks(Names, Deps, NewLocks,
[{Name, Source, 0} | NewUnlocks ++ Unlocks])
end;
{_, _, Level} = Lock when Level > 0 ->
case lists:keyfind(AtomName, 1, Deps) of
false ->
?PRV_ERROR({transitive_dependency, Name});
Dep -> % Dep has been promoted
{Source, NewLocks, NewUnlocks} = prepare_lock(Dep, Lock, Locks),
prepare_locks(Names, Deps, NewLocks,
[{Name, Source, 0} | NewUnlocks ++ Unlocks]) [{Name, Source, 0} | NewUnlocks ++ Unlocks])
end; end;
{_, _, Level} when Level > 0 ->
?PRV_ERROR({transitive_dependency, Name});
false -> false ->
?PRV_ERROR({unknown_dependency, Name}) ?PRV_ERROR({unknown_dependency, Name})
end. end.
prepare_lock(Dep, Lock, Locks) ->
Source = Source = case Dep of
{_, Src} -> Src;
{_, _, Src} -> Src
end,
{NewLocks, NewUnlocks} = unlock_higher_than(0, Locks -- [Lock]),
{Source, NewLocks, NewUnlocks}.
top_level_deps(Deps, Locks) -> top_level_deps(Deps, Locks) ->
[Dep || Dep <- Deps, lists:keymember(0, 3, Locks)]. [Dep || Dep <- Deps, lists:keymember(0, 3, Locks)].

+ 5
- 17
src/rebar_prv_xref.erl ファイルの表示

@ -36,7 +36,8 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) -> do(State) ->
{OriginalPath, XrefChecks} = prepare(State),
code:add_pathsa(rebar_state:code_paths(State, all_deps)),
XrefChecks = prepare(State),
%% Run xref checks %% Run xref checks
?INFO("Running cross reference analysis...", []), ?INFO("Running cross reference analysis...", []),
@ -45,9 +46,8 @@ do(State) ->
%% Run custom queries %% Run custom queries
QueryChecks = rebar_state:get(State, xref_queries, []), QueryChecks = rebar_state:get(State, xref_queries, []),
QueryResults = lists:foldl(fun check_query/2, [], QueryChecks), QueryResults = lists:foldl(fun check_query/2, [], QueryChecks),
ok = cleanup(OriginalPath),
stopped = xref:stop(xref),
rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)),
case XrefResults =:= [] andalso QueryResults =:= [] of case XrefResults =:= [] andalso QueryResults =:= [] of
true -> true ->
{ok, State}; {ok, State};
@ -100,10 +100,6 @@ prepare(State) ->
[{ok, _} = xref:add_directory(xref, rebar_app_info:ebin_dir(App)) [{ok, _} = xref:add_directory(xref, rebar_app_info:ebin_dir(App))
|| App <- rebar_state:project_apps(State)], || App <- rebar_state:project_apps(State)],
%% Save the code path prior to doing any further code path
%% manipulation
OriginalPath = code:get_path(),
%% Get list of xref checks we want to run %% Get list of xref checks we want to run
ConfXrefChecks = rebar_state:get(State, xref_checks, ConfXrefChecks = rebar_state:get(State, xref_checks,
[exports_not_used, [exports_not_used,
@ -112,15 +108,7 @@ prepare(State) ->
XrefChecks = sets:to_list(sets:intersection( XrefChecks = sets:to_list(sets:intersection(
sets:from_list(?SUPPORTED_XREFS), sets:from_list(?SUPPORTED_XREFS),
sets:from_list(ConfXrefChecks))), sets:from_list(ConfXrefChecks))),
{OriginalPath, XrefChecks}.
cleanup(Path) ->
%% Restore the code path using the provided path
true = rebar_utils:cleanup_code_path(Path),
%% Stop xref
stopped = xref:stop(xref),
ok.
XrefChecks.
xref_checks(XrefChecks) -> xref_checks(XrefChecks) ->
lists:foldl(fun run_xref_check/2, [], XrefChecks). lists:foldl(fun run_xref_check/2, [], XrefChecks).

+ 27
- 2
src/rebar_state.erl ファイルの表示

@ -3,6 +3,8 @@
-export([new/0, new/1, new/2, new/3, -export([new/0, new/1, new/2, new/3,
get/2, get/3, set/3, get/2, get/3, set/3,
code_paths/2, code_paths/3, update_code_paths/3,
opts/1, opts/2, opts/1, opts/2,
default/1, default/2, default/1, default/2,
@ -22,7 +24,7 @@
project_apps/1, project_apps/2, project_apps/1, project_apps/2,
deps_to_build/1, deps_to_build/2, deps_to_build/1, deps_to_build/2,
all_deps/1, all_deps/2,
all_deps/1, all_deps/2, update_all_deps/2,
namespace/1, namespace/2, namespace/1, namespace/2,
deps_names/1, deps_names/1,
@ -40,6 +42,7 @@
-record(state_t, {dir :: file:name(), -record(state_t, {dir :: file:name(),
opts = dict:new() :: rebar_dict(), opts = dict:new() :: rebar_dict(),
code_paths = dict:new() :: rebar_dict(),
default = dict:new() :: rebar_dict(), default = dict:new() :: rebar_dict(),
escript_path :: undefined | file:filename_all(), escript_path :: undefined | file:filename_all(),
@ -62,7 +65,7 @@
-export_type([t/0]). -export_type([t/0]).
-type t() :: record(state_t).
-type t() :: #state_t{}.
-spec new() -> t(). -spec new() -> t().
new() -> new() ->
@ -132,6 +135,25 @@ default(#state_t{default=Opts}) ->
default(State, Opts) -> default(State, Opts) ->
State#state_t{default=Opts}. State#state_t{default=Opts}.
code_paths(#state_t{code_paths=CodePaths}, Key) ->
case dict:find(Key, CodePaths) of
{ok, CodePath} ->
CodePath;
_ ->
[]
end.
code_paths(State=#state_t{code_paths=CodePaths}, Key, CodePath) ->
State#state_t{code_paths=dict:store(Key, CodePath, CodePaths)}.
update_code_paths(State=#state_t{code_paths=CodePaths}, Key, CodePath) ->
case dict:is_key(Key, CodePaths) of
true ->
State#state_t{code_paths=dict:append_list(Key, CodePath, CodePaths)};
false ->
State#state_t{code_paths=dict:store(Key, CodePath, CodePaths)}
end.
opts(#state_t{opts=Opts}) -> opts(#state_t{opts=Opts}) ->
Opts. Opts.
@ -310,6 +332,9 @@ all_deps(#state_t{all_deps=Apps}) ->
all_deps(State=#state_t{}, NewApps) -> all_deps(State=#state_t{}, NewApps) ->
State#state_t{all_deps=NewApps}. State#state_t{all_deps=NewApps}.
update_all_deps(State=#state_t{all_deps=Apps}, NewApps) ->
State#state_t{all_deps=Apps++NewApps}.
namespace(#state_t{namespace=Namespace}) -> namespace(#state_t{namespace=Namespace}) ->
Namespace. Namespace.

+ 26
- 8
src/rebar_templater.erl ファイルの表示

@ -266,17 +266,29 @@ replace_var([H|T], Acc, Vars) ->
%% Load a list of all the files in the escript and on disk %% Load a list of all the files in the escript and on disk
find_templates(State) -> find_templates(State) ->
%% Cache the files since we'll potentially need to walk it several times
%% over the course of a run.
Files = cache_escript_files(State),
DiskTemplates = find_disk_templates(State),
{MainTemplates, Files} =
case rebar_state:escript_path(State) of
undefined ->
{find_priv_templates(State), []};
_ ->
%% Cache the files since we'll potentially need to walk it several times
%% over the course of a run.
F = cache_escript_files(State),
{find_escript_templates(F), F}
end,
AvailTemplates = find_available_templates(DiskTemplates,
MainTemplates),
?DEBUG("Available templates: ~p\n", [AvailTemplates]),
{AvailTemplates, Files}.
%% Build a list of available templates
find_available_templates(TemplateList1, TemplateList2) ->
AvailTemplates = prioritize_templates( AvailTemplates = prioritize_templates(
tag_names(find_disk_templates(State)),
tag_names(find_escript_templates(Files))),
tag_names(TemplateList1),
tag_names(TemplateList2)),
?DEBUG("Available templates: ~p\n", [AvailTemplates]), ?DEBUG("Available templates: ~p\n", [AvailTemplates]),
{AvailTemplates, Files}.
AvailTemplates.
%% Scan the current escript for available files %% Scan the current escript for available files
cache_escript_files(State) -> cache_escript_files(State) ->
@ -293,6 +305,12 @@ find_escript_templates(Files) ->
|| {Name, _Bin} <- Files, || {Name, _Bin} <- Files,
re:run(Name, ?TEMPLATE_RE, [{capture, none}]) == match]. re:run(Name, ?TEMPLATE_RE, [{capture, none}]) == match].
find_priv_templates(State) ->
OtherTemplates = rebar_utils:find_files(code:priv_dir(rebar), ?TEMPLATE_RE),
HomeFiles = rebar_utils:find_files(rebar_dir:template_dir(State),
?TEMPLATE_RE, true), % recursive
[{file, F} || F <- OtherTemplates ++ HomeFiles].
%% Fetch template indexes that sit on disk in the user's HOME %% Fetch template indexes that sit on disk in the user's HOME
find_disk_templates(State) -> find_disk_templates(State) ->
OtherTemplates = find_other_templates(State), OtherTemplates = find_other_templates(State),
@ -394,7 +412,7 @@ write_file(Output, Data, Force) ->
-spec make_template_name(string(), term()) -> module(). -spec make_template_name(string(), term()) -> module().
make_template_name(Base, Value) -> make_template_name(Base, Value) ->
%% Seed so we get different values each time %% Seed so we get different values each time
random:seed(erlang:now()),
random:seed(os:timestamp()),
Hash = erlang:phash2(Value), Hash = erlang:phash2(Value),
Ran = random:uniform(10000000), Ran = random:uniform(10000000),
erlang:list_to_atom(Base ++ "_" ++ erlang:list_to_atom(Base ++ "_" ++

+ 0
- 8
src/rebar_utils.erl ファイルの表示

@ -42,7 +42,6 @@
erl_to_mod/1, erl_to_mod/1,
beams/1, beams/1,
find_executable/1, find_executable/1,
expand_code_path/0,
vcs_vsn/2, vcs_vsn/2,
deprecated/3, deprecated/3,
deprecated/4, deprecated/4,
@ -177,13 +176,6 @@ find_executable(Name) ->
"\"" ++ filename:nativename(Path) ++ "\"" "\"" ++ filename:nativename(Path) ++ "\""
end. end.
%% Convert all the entries in the code path to absolute paths.
expand_code_path() ->
CodePath = lists:foldl(fun(Path, Acc) ->
[filename:absname(Path) | Acc]
end, [], code:get_path()),
code:set_path(lists:reverse(CodePath)).
deprecated(Old, New, Opts, When) when is_list(Opts) -> deprecated(Old, New, Opts, When) when is_list(Opts) ->
case lists:member(Old, Opts) of case lists:member(Old, Opts) of
true -> true ->

+ 1
- 1
test/mock_pkg_resource.erl ファイルの表示

@ -152,7 +152,7 @@ find_parts([{AppName, Deps}|Rest], Skip, Acc) ->
end. end.
to_graph_parts(Dict) -> to_graph_parts(Dict) ->
LastUpdated = now(),
LastUpdated = os:timestamp(),
dict:fold(fun(K,V,{Ks,Vs}) -> dict:fold(fun(K,V,{Ks,Vs}) ->
{_,Deps} = lists:keyfind(<<"deps">>, 1, V), {_,Deps} = lists:keyfind(<<"deps">>, 1, V),
{[{K,LastUpdated}|Ks], {[{K,LastUpdated}|Ks],

+ 8
- 5
test/rebar_compile_SUITE.erl ファイルの表示

@ -102,10 +102,11 @@ build_checkout_deps(Config) ->
Deps = [{list_to_atom(Name2), Vsn2, {git, "", ""}}], Deps = [{list_to_atom(Name2), Vsn2, {git, "", ""}}],
{ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, Deps}])), {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, Deps}])),
rebar_test_utils:run_and_check(
{ok, State} = rebar_test_utils:run_and_check(
Config, RebarConfig, ["compile"], Config, RebarConfig, ["compile"],
{ok, [{app, Name1}, {checkout, Name2}]} {ok, [{app, Name1}, {checkout, Name2}]}
), ),
code:add_paths(rebar_state:code_paths(State, all_deps)),
ok = application:load(list_to_atom(Name2)), ok = application:load(list_to_atom(Name2)),
Loaded = application:loaded_applications(), Loaded = application:loaded_applications(),
{_, _, Vsn2} = lists:keyfind(list_to_atom(Name2), 1, Loaded). {_, _, Vsn2} = lists:keyfind(list_to_atom(Name2), 1, Loaded).
@ -307,10 +308,11 @@ deps_in_path(Config) ->
?assertEqual([], [Path || Path <- code:get_path(), ?assertEqual([], [Path || Path <- code:get_path(),
{match, _} <- [re:run(Path, PkgName)]]), {match, _} <- [re:run(Path, PkgName)]]),
%% Build things %% Build things
rebar_test_utils:run_and_check(
{ok, State} = rebar_test_utils:run_and_check(
Config, RConf, ["compile"], Config, RConf, ["compile"],
{ok, [{app, Name}, {dep, DepName}, {dep, PkgName}]} {ok, [{app, Name}, {dep, DepName}, {dep, PkgName}]}
), ),
code:add_paths(rebar_state:code_paths(State, all_deps)),
%% Find src name in there %% Find src name in there
?assertNotEqual([], [Path || Path <- code:get_path(), ?assertNotEqual([], [Path || Path <- code:get_path(),
{match, _} <- [re:run(Path, DepName)]]), {match, _} <- [re:run(Path, DepName)]]),
@ -326,11 +328,12 @@ deps_in_path(Config) ->
?assertEqual([], [Path || Path <- code:get_path(), ?assertEqual([], [Path || Path <- code:get_path(),
{match, _} <- [re:run(Path, PkgName)]]), {match, _} <- [re:run(Path, PkgName)]]),
%% Rebuild %% Rebuild
rebar_test_utils:run_and_check(
{ok, State1} = rebar_test_utils:run_and_check(
Config, RConf, ["compile"], Config, RConf, ["compile"],
{ok, [{app, Name}, {dep, DepName}, {dep, PkgName}]} {ok, [{app, Name}, {dep, DepName}, {dep, PkgName}]}
), ),
%% Find src name in there %% Find src name in there
code:add_paths(rebar_state:code_paths(State1, all_deps)),
?assertNotEqual([], [Path || Path <- code:get_path(), ?assertNotEqual([], [Path || Path <- code:get_path(),
{match, _} <- [re:run(Path, DepName)]]), {match, _} <- [re:run(Path, DepName)]]),
%% find pkg name in there %% find pkg name in there
@ -373,11 +376,11 @@ checkout_priority(Config) ->
%% Rebuild and make sure the checkout apps are in path %% Rebuild and make sure the checkout apps are in path
code:set_path(StartPaths), code:set_path(StartPaths),
rebar_test_utils:run_and_check(
{ok, State} = rebar_test_utils:run_and_check(
Config, RConf, ["compile"], Config, RConf, ["compile"],
{ok, [{app, Name}, {checkout, DepName}, {checkout, PkgName}]} {ok, [{app, Name}, {checkout, DepName}, {checkout, PkgName}]}
), ),
code:add_paths(rebar_state:code_paths(State, all_deps)),
[DepPath] = [Path || Path <- code:get_path(), [DepPath] = [Path || Path <- code:get_path(),
{match, _} <- [re:run(Path, DepName)]], {match, _} <- [re:run(Path, DepName)]],
[PkgPath] = [Path || Path <- code:get_path(), [PkgPath] = [Path || Path <- code:get_path(),

+ 6
- 6
test/rebar_eunit_SUITE.erl ファイルの表示

@ -164,8 +164,8 @@ test_basic_defines(Config) ->
AppOpts = proplists:get_value(options, App:module_info(compile), []), AppOpts = proplists:get_value(options, App:module_info(compile), []),
SuiteOpts = proplists:get_value(options, Suite:module_info(compile), []), SuiteOpts = proplists:get_value(options, Suite:module_info(compile), []),
Expect = [{d, some_define}], Expect = [{d, some_define}],
lists:foreach(fun(Expect) -> true = lists:member(Expect, AppOpts) end, Expect),
lists:foreach(fun(Expect) -> true = lists:member(Expect, SuiteOpts) end, Expect).
lists:foreach(fun(E) -> true = lists:member(E, AppOpts) end, Expect),
lists:foreach(fun(E) -> true = lists:member(E, SuiteOpts) end, Expect).
test_multi_defines(Config) -> test_multi_defines(Config) ->
AppDir = ?config(apps, Config), AppDir = ?config(apps, Config),
@ -198,10 +198,10 @@ test_multi_defines(Config) ->
AppOpts2 = proplists:get_value(options, App2:module_info(compile), []), AppOpts2 = proplists:get_value(options, App2:module_info(compile), []),
SuiteOpts2 = proplists:get_value(options, Suite2:module_info(compile), []), SuiteOpts2 = proplists:get_value(options, Suite2:module_info(compile), []),
Expect = [{d, some_define}], Expect = [{d, some_define}],
lists:foreach(fun(Expect) -> true = lists:member(Expect, AppOpts1) end, Expect),
lists:foreach(fun(Expect) -> true = lists:member(Expect, SuiteOpts1) end, Expect),
lists:foreach(fun(Expect) -> true = lists:member(Expect, AppOpts2) end, Expect),
lists:foreach(fun(Expect) -> true = lists:member(Expect, SuiteOpts2) end, Expect).
lists:foreach(fun(E) -> true = lists:member(E, AppOpts1) end, Expect),
lists:foreach(fun(E) -> true = lists:member(E, SuiteOpts1) end, Expect),
lists:foreach(fun(E) -> true = lists:member(E, AppOpts2) end, Expect),
lists:foreach(fun(E) -> true = lists:member(E, SuiteOpts2) end, Expect).
test_single_app_flag(Config) -> test_single_app_flag(Config) ->
AppDir = ?config(apps, Config), AppDir = ?config(apps, Config),

+ 79
- 2
test/rebar_install_deps_SUITE.erl ファイルの表示

@ -2,6 +2,7 @@
-compile(export_all). -compile(export_all).
-include_lib("common_test/include/ct.hrl"). -include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
-include_lib("kernel/include/file.hrl").
all() -> [{group, git}, {group, pkg}]. all() -> [{group, git}, {group, pkg}].
@ -9,7 +10,7 @@ groups() ->
[{all, [], [flat, pick_highest_left, pick_highest_right, [{all, [], [flat, pick_highest_left, pick_highest_right,
pick_smallest1, pick_smallest2, pick_smallest1, pick_smallest2,
circular1, circular2, circular_skip, circular1, circular2, circular_skip,
fail_conflict]},
fail_conflict, default_profile, nondefault_profile]},
{git, [], [{group, all}]}, {git, [], [{group, all}]},
{pkg, [], [{group, all}]}]. {pkg, [], [{group, all}]}].
@ -114,7 +115,17 @@ deps(fail_conflict) ->
{[{"B", [{"C", "2", []}]}, {[{"B", [{"C", "2", []}]},
{"C", "1", []}], {"C", "1", []}],
[{"C","2"}], [{"C","2"}],
rebar_abort}.
rebar_abort};
deps(default_profile) ->
{[{"B", []},
{"C", []}],
[],
{ok, ["B", "C"]}};
deps(nondefault_profile) ->
{[{"B", []},
{"C", []}],
[],
{ok, ["B", "C"]}}.
setup_project(fail_conflict, Config0, Deps) -> setup_project(fail_conflict, Config0, Deps) ->
DepsType = ?config(deps_type, Config0), DepsType = ?config(deps_type, Config0),
@ -134,6 +145,25 @@ setup_project(fail_conflict, Config0, Deps) ->
mock_pkg_resource:mock([{pkgdeps, rebar_test_utils:flat_pkgdeps(Deps)}]) mock_pkg_resource:mock([{pkgdeps, rebar_test_utils:flat_pkgdeps(Deps)}])
end, end,
[{rebarconfig, RebarConf} | Config]; [{rebarconfig, RebarConf} | Config];
setup_project(nondefault_profile, Config0, Deps) ->
DepsType = ?config(deps_type, Config0),
Config = rebar_test_utils:init_rebar_state(
Config0,
"nondefault_profile_"++atom_to_list(DepsType)++"_"
),
AppDir = ?config(apps, Config),
rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]),
TopDeps = rebar_test_utils:top_level_deps(Deps),
RebarConf = rebar_test_utils:create_config(AppDir, [{profiles, [
{nondef, [{deps, TopDeps}]}
]}]),
case DepsType of
git ->
mock_git_resource:mock([{deps, rebar_test_utils:flat_deps(Deps)}]);
pkg ->
mock_pkg_resource:mock([{pkgdeps, rebar_test_utils:flat_pkgdeps(Deps)}])
end,
[{rebarconfig, RebarConf} | Config];
setup_project(Case, Config0, Deps) -> setup_project(Case, Config0, Deps) ->
DepsType = ?config(deps_type, Config0), DepsType = ?config(deps_type, Config0),
Config = rebar_test_utils:init_rebar_state( Config = rebar_test_utils:init_rebar_state(
@ -174,6 +204,53 @@ fail_conflict(Config) ->
), ),
check_warnings(error_calls(), ?config(warnings, Config), ?config(deps_type, Config)). check_warnings(error_calls(), ?config(warnings, Config), ?config(deps_type, Config)).
default_profile(Config) ->
{ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
AppDir = ?config(apps, Config),
{ok, Apps} = Expect = ?config(expect, Config),
rebar_test_utils:run_and_check(
Config, RebarConfig, ["as", "profile", "install_deps"], Expect
),
check_warnings(error_calls(), ?config(warnings, Config), ?config(deps_type, Config)),
BuildDir = filename:join([AppDir, "_build"]),
[?assertMatch({ok, #file_info{type=directory}},
file:read_file_info(filename:join([BuildDir, "default", "lib", App])))
|| {dep, App} <- Apps],
[?assertMatch({ok, #file_info{type=directory}}, % somehow symlinks return dirs
file:read_file_info(filename:join([BuildDir, "profile", "lib", App])))
|| {dep, App} <- Apps],
%% A second run to another profile also links default to the right spot
rebar_test_utils:run_and_check(
Config, RebarConfig, ["as", "other", "install_deps"], Expect
),
[?assertMatch({ok, #file_info{type=directory}}, % somehow symlinks return dirs
file:read_file_info(filename:join([BuildDir, "other", "lib", App])))
|| {dep, App} <- Apps].
nondefault_profile(Config) ->
{ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
AppDir = ?config(apps, Config),
{ok, Apps} = Expect = ?config(expect, Config),
rebar_test_utils:run_and_check(
Config, RebarConfig, ["as", "nondef", "install_deps"], Expect
),
check_warnings(error_calls(), ?config(warnings, Config), ?config(deps_type, Config)),
BuildDir = filename:join([AppDir, "_build"]),
[?assertMatch({error, enoent},
file:read_file_info(filename:join([BuildDir, "default", "lib", App])))
|| {dep, App} <- Apps],
[?assertMatch({ok, #file_info{type=directory}},
file:read_file_info(filename:join([BuildDir, "nondef", "lib", App])))
|| {dep, App} <- Apps],
%% A second run to another profile doesn't link dependencies
rebar_test_utils:run_and_check(
Config, RebarConfig, ["as", "other", "install_deps"], Expect
),
[?assertMatch({error, enoent},
file:read_file_info(filename:join([BuildDir, "default", "lib", App])))
|| {dep, App} <- Apps].
run(Config) -> run(Config) ->
{ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
rebar_test_utils:run_and_check( rebar_test_utils:run_and_check(

+ 42
- 3
test/rebar_profiles_SUITE.erl ファイルの表示

@ -9,6 +9,7 @@
profile_merge_keys/1, profile_merge_keys/1,
explicit_profile_deduplicate_deps/1, explicit_profile_deduplicate_deps/1,
implicit_profile_deduplicate_deps/1, implicit_profile_deduplicate_deps/1,
all_deps_code_paths/1,
profile_merges/1, profile_merges/1,
same_profile_deduplication/1, same_profile_deduplication/1,
stack_deduplication/1, stack_deduplication/1,
@ -25,7 +26,7 @@
-include_lib("kernel/include/file.hrl"). -include_lib("kernel/include/file.hrl").
all() -> all() ->
[profile_new_key, profile_merge_keys, profile_merges,
[profile_new_key, profile_merge_keys, all_deps_code_paths, profile_merges,
explicit_profile_deduplicate_deps, implicit_profile_deduplicate_deps, explicit_profile_deduplicate_deps, implicit_profile_deduplicate_deps,
same_profile_deduplication, stack_deduplication, same_profile_deduplication, stack_deduplication,
add_to_profile, add_to_existing_profile, add_to_profile, add_to_existing_profile,
@ -161,6 +162,39 @@ implicit_profile_deduplicate_deps(Config) ->
,{dep, "a", "1.0.0"} ,{dep, "a", "1.0.0"}
,{dep, "b", "2.0.0"}]}). ,{dep, "b", "2.0.0"}]}).
all_deps_code_paths(Config) ->
AppDir = ?config(apps, Config),
AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
,{"b", "2.0.0", []}]),
mock_git_resource:mock([{deps, rebar_test_utils:flat_deps(AllDeps)}]),
Name = rebar_test_utils:create_random_name("all_deps_code_paths"),
Vsn = rebar_test_utils:create_random_vsn(),
rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
Deps = rebar_test_utils:top_level_deps(
rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}])),
ProfileDeps = rebar_test_utils:top_level_deps(
rebar_test_utils:expand_deps(git, [{"b", "2.0.0", []}])),
RebarConfig = [{deps, Deps},
{profiles,
[{all_deps_test,
[{deps, ProfileDeps}]}]}],
os:putenv("REBAR_PROFILE", "all_deps_test"),
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig,
["compile"], {ok, [{app, Name}
,{dep, "a", "1.0.0"}
,{dep, "b", "2.0.0"}]}),
os:putenv("REBAR_PROFILE", ""),
Paths = rebar_state:code_paths(State, all_deps),
Path = lists:reverse(["_build", "all_deps_test", "lib", "b", "ebin"]),
?assert(lists:any(fun(X) ->
Path =:= lists:sublist(lists:reverse(filename:split(X)), 5)
end, Paths)).
profile_merges(_Config) -> profile_merges(_Config) ->
RebarConfig = [{test1, [{key1, 1, 2}, key2]}, RebarConfig = [{test1, [{key1, 1, 2}, key2]},
@ -296,6 +330,9 @@ profiles_remain_applied_with_config_present(Config) ->
rebar_test_utils:run_and_check(Config, RebarConfig, rebar_test_utils:run_and_check(Config, RebarConfig,
["as", "not_ok", "compile"], {ok, [{app, Name}]}), ["as", "not_ok", "compile"], {ok, [{app, Name}]}),
Path = filename:join([AppDir, "_build", "not_ok", "lib", Name, "ebin"]),
code:add_patha(Path),
Mod = list_to_atom("not_a_real_src_" ++ Name), Mod = list_to_atom("not_a_real_src_" ++ Name),
true = lists:member({d, not_ok}, proplists:get_value(options, Mod:module_info(compile), [])). true = lists:member({d, not_ok}, proplists:get_value(options, Mod:module_info(compile), [])).
@ -329,7 +366,8 @@ test_profile_applied_before_compile(Config) ->
RebarConfig = [{erl_opts, [{d, some_define}]}], RebarConfig = [{erl_opts, [{d, some_define}]}],
rebar_test_utils:create_config(AppDir, RebarConfig), rebar_test_utils:create_config(AppDir, RebarConfig),
rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], {ok, [{app, Name}]}),
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], {ok, [{app, Name}]}),
code:add_paths(rebar_state:code_paths(State, all_deps)),
S = list_to_atom("not_a_real_src_" ++ Name), S = list_to_atom("not_a_real_src_" ++ Name),
true = lists:member({d, 'TEST'}, proplists:get_value(options, S:module_info(compile), [])). true = lists:member({d, 'TEST'}, proplists:get_value(options, S:module_info(compile), [])).
@ -344,7 +382,8 @@ test_profile_applied_before_eunit(Config) ->
RebarConfig = [{erl_opts, [{d, some_define}]}], RebarConfig = [{erl_opts, [{d, some_define}]}],
rebar_test_utils:create_config(AppDir, RebarConfig), rebar_test_utils:create_config(AppDir, RebarConfig),
rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], {ok, [{app, Name}]}),
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], {ok, [{app, Name}]}),
code:add_paths(rebar_state:code_paths(State, all_deps)),
T = list_to_atom("not_a_real_src_" ++ Name ++ "_tests"), T = list_to_atom("not_a_real_src_" ++ Name ++ "_tests"),
true = lists:member({d, 'TEST'}, proplists:get_value(options, T:module_info(compile), [])). true = lists:member({d, 'TEST'}, proplists:get_value(options, T:module_info(compile), [])).

+ 4
- 3
test/rebar_test_utils.erl ファイルの表示

@ -56,7 +56,8 @@ run_and_check(Config, RebarConfig, Command, Expect) ->
?assertEqual({error, Reason}, Res); ?assertEqual({error, Reason}, Res);
{ok, Expected} -> {ok, Expected} ->
{ok, _} = Res, {ok, _} = Res,
check_results(AppDir, Expected);
check_results(AppDir, Expected),
Res;
return -> return ->
Res Res
end end
@ -103,12 +104,12 @@ create_config(AppDir, Contents) ->
%% @doc Util to create a random variation of a given name. %% @doc Util to create a random variation of a given name.
create_random_name(Name) -> create_random_name(Name) ->
random:seed(erlang:now()),
random:seed(os:timestamp()),
Name ++ erlang:integer_to_list(random:uniform(1000000)). Name ++ erlang:integer_to_list(random:uniform(1000000)).
%% @doc Util to create a random variation of a given version. %% @doc Util to create a random variation of a given version.
create_random_vsn() -> create_random_vsn() ->
random:seed(erlang:now()),
random:seed(os:timestamp()),
lists:flatten([erlang:integer_to_list(random:uniform(100)), lists:flatten([erlang:integer_to_list(random:uniform(100)),
".", erlang:integer_to_list(random:uniform(100)), ".", erlang:integer_to_list(random:uniform(100)),
".", erlang:integer_to_list(random:uniform(100))]). ".", erlang:integer_to_list(random:uniform(100))]).

+ 40
- 0
test/rebar_unlock_SUITE.erl ファイルの表示

@ -0,0 +1,40 @@
-module(rebar_unlock_SUITE).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
-compile(export_all).
all() -> [unlock, unlock_all].
init_per_testcase(Case, Config0) ->
Config = rebar_test_utils:init_rebar_state(Config0, atom_to_list(Case)),
Lockfile = filename:join(?config(apps, Config), "rebar.lock"),
ec_file:copy(filename:join(?config(data_dir, Config), "rebar.lock"),
Lockfile),
[{lockfile, Lockfile} | Config].
end_per_testcase(_, Config) ->
Config.
unlock(Config) ->
Locks = read_locks(Config),
rebar_test_utils:run_and_check(Config, [], ["unlock", "fakeapp"], {ok, []}),
Locks = read_locks(Config),
rebar_test_utils:run_and_check(Config, [], ["unlock", "uuid"], {ok, []}),
?assertEqual(Locks -- ["uuid"], read_locks(Config)),
rebar_test_utils:run_and_check(Config, [], ["unlock", "gproc,itc"], {ok, []}),
?assertEqual(Locks -- ["uuid","gproc","itc"], read_locks(Config)),
rebar_test_utils:run_and_check(Config, [], ["unlock", string:join(Locks,",")], {ok, []}),
?assertEqual({error, enoent}, read_locks(Config)),
ok.
unlock_all(Config) ->
[_|_] = read_locks(Config),
rebar_test_utils:run_and_check(Config, [], ["unlock"], {ok, []}),
?assertEqual({error, enoent}, read_locks(Config)),
ok.
read_locks(Config) ->
case file:consult(?config(lockfile, Config)) of
{ok, [Locks]} -> [binary_to_list(element(1,Lock)) || Lock <- Locks];
Other -> Other
end.

+ 40
- 0
test/rebar_unlock_SUITE_data/rebar.lock ファイルの表示

@ -0,0 +1,40 @@
[{<<"meck">>,
{git,"git://github.com/eproxus/meck",
{ref,"69664df5d0e01a0ae27efb62831d6eea45cc1cd4"}},
3},
{<<"itc">>,
{git,"git://github.com/ferd/Interval-Tree-Clocks.git",
{ref,"168449da42871892f6047733edddf33936dd660f"}},
2},
{<<"bitcask">>,
{git,"https://github.com/basho/bitcask.git",
{ref,"c3e9cc5e64bcfd6e342a85932a90428cfdc1ee2d"}},
2},
{<<"quickrand">>,
{git,"https://github.com/okeuday/quickrand.git",
{ref,"0395a10b94472ccbe38b62bbfa9d0fc1ddac1dd7"}},
1},
{<<"merklet">>,
{git,"git://github.com/ferd/merklet.git",
{ref,"21b5797a21ab6aa1ddb6740799372d2d4b6a6054"}},
1},
{<<"interclock">>,
{git,"git://github.com/ferd/interclock.git",
{ref,"6a8b7443fa200da16d819f058e4dc8a0a75eca1e"}},
1},
{<<"gproc">>,
{git,"git://github.com/uwiger/gproc.git",
{ref,"7655bddc4397d0cc3f7c4d95e7b96790605946fe"}},
1},
{<<"uuid">>,
{git,"https://github.com/okeuday/uuid.git",
{ref,"f7c141c8359cd690faba0d2684b449a07db8e915"}},
0},
{<<"peeranha">>,
{git,"https://github.com/ferd/peeranha.git",
{ref,"3bdbdadf6e34a1705bf2669eb28acd32a4fc9166"}},
0},
{<<"file_monitor">>,
{git,"https://github.com/richcarl/file_monitor.git",
{ref,"4910b991bf3166377985d7ed961665c4b24e3de6"}},
0}].

+ 13
- 2
test/rebar_upgrade_SUITE.erl ファイルの表示

@ -10,7 +10,7 @@ groups() ->
pair_a, pair_b, pair_ab, pair_c, pair_all, pair_a, pair_b, pair_ab, pair_c, pair_all,
triplet_a, triplet_b, triplet_c, triplet_a, triplet_b, triplet_c,
tree_a, tree_b, tree_c, tree_c2, tree_ac, tree_all, tree_a, tree_b, tree_c, tree_c2, tree_ac, tree_all,
delete_d]},
delete_d, promote]},
{git, [], [{group, all}]}, {git, [], [{group, all}]},
{pkg, [], [{group, all}]}]. {pkg, [], [{group, all}]}].
@ -351,7 +351,17 @@ upgrades(delete_d) ->
], ],
["A","B", "C"], ["A","B", "C"],
%% upgrade vs. new tree %% upgrade vs. new tree
{"", [{"A","2"}, "B", "C"]}}.
{"", [{"A","2"}, "B", "C"]}};
upgrades(promote) ->
{[{"A", "1", [{"C", "1", []}]},
{"B", "1", [{"D", "1", []}]}
],
[{"A", "2", [{"C", "2", []}]},
{"B", "2", [{"D", "2", []}]},
{"C", "3", []}
],
["A","B","C","D"],
{"C", [{"A","1"},{"C","3"},{"B","1"},{"D","1"}]}}.
%% TODO: add a test that verifies that unlocking files and then %% TODO: add a test that verifies that unlocking files and then
%% running the upgrade code is enough to properly upgrade things. %% running the upgrade code is enough to properly upgrade things.
@ -414,6 +424,7 @@ tree_c(Config) -> run(Config).
tree_c2(Config) -> run(Config). tree_c2(Config) -> run(Config).
tree_ac(Config) -> run(Config). tree_ac(Config) -> run(Config).
tree_all(Config) -> run(Config). tree_all(Config) -> run(Config).
promote(Config) -> run(Config).
delete_d(Config) -> delete_d(Config) ->
meck:new(rebar_log, [no_link, passthrough]), meck:new(rebar_log, [no_link, passthrough]),

+ 2
- 2
test/rebar_xref_SUITE.erl ファイルの表示

@ -44,7 +44,7 @@ init_per_testcase(Case, Config) ->
[{app_name, Name}, [{app_name, Name},
{rebar_config, RebarConfig} | UpdConfig]. {rebar_config, RebarConfig} | UpdConfig].
end_per_testcase(_, Config) ->
end_per_testcase(_, _Config) ->
ok. ok.
all() -> all() ->
@ -112,7 +112,7 @@ verify_test_results(xref_test, AppName, XrefResults, _QueryResults) ->
ok; ok;
verify_test_results(xref_ignore_test, AppName, XrefResults, _QueryResults) -> verify_test_results(xref_ignore_test, AppName, XrefResults, _QueryResults) ->
AppModules = ["behaviour1", "behaviour2", "mymod", "othermod", "somemod"], AppModules = ["behaviour1", "behaviour2", "mymod", "othermod", "somemod"],
[Behaviour1Mod, Behaviour2Mod, MyMod, OtherMod, SomeMod] =
[_Behaviour1Mod, _Behaviour2Mod, _MyMod, _OtherMod, SomeMod] =
[list_to_atom(AppName ++ "_" ++ Mod) || Mod <- AppModules], [list_to_atom(AppName ++ "_" ++ Mod) || Mod <- AppModules],
UndefFuns = proplists:get_value(undefined_functions, XrefResults), UndefFuns = proplists:get_value(undefined_functions, XrefResults),
?assertNot(lists:keymember(undefined_function_calls, 1, XrefResults)), ?assertNot(lists:keymember(undefined_function_calls, 1, XrefResults)),

読み込み中…
キャンセル
保存