diff options
author | Matwey V. Kornilov <matwey.kornilov@gmail.com> | 2016-03-02 16:30:30 +0300 |
---|---|---|
committer | Matwey V. Kornilov <matwey.kornilov@gmail.com> | 2016-03-18 11:05:18 +0300 |
commit | 16bc8f77254d58913748e3d878b48be290a5fa89 (patch) | |
tree | 774fe5904ceca628b7cbe876bd767864299ec766 | |
parent | 384af7ef191b8b3f52b212f6b7f02ace786ba2a9 (diff) | |
download | rebar-16bc8f77254d58913748e3d878b48be290a5fa89.tar.gz |
Introduce REBAR_VSN_CACHE_FILE env variable to load/save vsn cache
When REBAR_VSN_CACHE_FILE is set, then vsn cache is loaded from
this file on rebar start and updated when new data.
Under specific circumstances (i.e. in build environments),
full git tree may not be available, but only its snapshot.
We need a way to use preheat vsn cache instead of invocing
git command.
Signed-off-by: Matwey V. Kornilov <matwey.kornilov@gmail.com>
-rw-r--r-- | inttest/vsn_cache/main.erl | 13 | ||||
-rw-r--r-- | inttest/vsn_cache/vsn_cache_rt.erl | 90 | ||||
-rw-r--r-- | src/rebar.erl | 3 | ||||
-rw-r--r-- | src/rebar_core.erl | 2 | ||||
-rw-r--r-- | src/rebar_utils.erl | 22 |
5 files changed, 127 insertions, 3 deletions
diff --git a/inttest/vsn_cache/main.erl b/inttest/vsn_cache/main.erl new file mode 100644 index 0000000..67b6465 --- /dev/null +++ b/inttest/vsn_cache/main.erl @@ -0,0 +1,13 @@ +-module(main). +-behaviour(application). + +-export([start/0,start/1,start/2,stop/1]). + +start() -> + start(permanent). +start(_Restart) -> + ok. +start(_Type,_Args) -> + ok. +stop(_State) -> + ok. diff --git a/inttest/vsn_cache/vsn_cache_rt.erl b/inttest/vsn_cache/vsn_cache_rt.erl new file mode 100644 index 0000000..b482888 --- /dev/null +++ b/inttest/vsn_cache/vsn_cache_rt.erl @@ -0,0 +1,90 @@ +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% ex: ts=4 sw=4 et +-module(vsn_cache_rt). + +-compile(export_all). + +setup([Target]) -> + retest_utils:load_module(filename:join(Target, "inttest_utils.erl")), + ok. + +files() -> + [ + %% Cache save check + {create, "save/src/save.app.src", app(save, [main])}, + {create, "save/vsn_cache_file", ""}, + {copy, "main.erl", "save/src/main.erl"}, + + %% Cache load check + {create, "load/src/load.app.src", app(load, [main])}, + {copy, "main.erl", "load/src/main.erl"} + ] ++ inttest_utils:rebar_setup(). + +apply_cmds([], _Params) -> + ok; +apply_cmds([Cmd | Rest], Params) -> + io:format("Running: ~s (~p)\n", [Cmd, Params]), + {ok, _} = retest_sh:run(Cmd, Params), + apply_cmds(Rest, Params). + +run_save(Dir) -> + GitCmds = ["git init", + "git add -A", + "git config user.email 'vsn_cache@example.com'", + "git config user.name 'vsn_cache'", + "git commit -a -m \"Initial Commit\""], + AppDir = filename:join(Dir, "save"), + EbinDir = filename:join(AppDir, "ebin"), + AppFile = filename:join(EbinDir, "save.app"), + VsnCacheFile = filename:join(AppDir, "vsn_cache_file"), + Env = [{"REBAR_VSN_CACHE_FILE", VsnCacheFile}], + + %% Initialize test git repository + ok = apply_cmds(GitCmds, [{dir, AppDir}]), + %% Compile test project with vsn cache enabled + {ok, _} = retest_sh:run("../rebar -v compile", [{env, Env}, {dir, AppDir}]), + %% Vsn cache file has an entry + {ok, [{{git, AppDir}, Hash}]} = file:consult(VsnCacheFile), + %% This vsn entry must coincide with entry from ebin/save.app + {ok, [{application, save, PropList}]} = file:consult(AppFile), + Hash = proplists:get_value(vsn, PropList), + ok. + +run_load(Dir) -> + AppDir = filename:join(Dir, "load"), + EbinDir = filename:join(AppDir, "ebin"), + AppFile = filename:join(EbinDir, "load.app"), + VsnCacheFile = filename:join(AppDir, "vsn_cache_file"), + Hash = "deadbeef", + CacheEntries = [{{git, AppDir}, Hash}], + Env = [{"REBAR_VSN_CACHE_FILE", VsnCacheFile}], + + %% Initialize dummy vsn cache file + vsn_cache_file(VsnCacheFile, CacheEntries), + %% Compile test project with vsn cache enabled + {ok, _} = retest_sh:run("../rebar -v compile", [{env, Env}, {dir, AppDir}]), + %% This vsn entry in cache file must coincide with entry in ebin/load.app + {ok, [{application, load, PropList}]} = file:consult(AppFile), + Hash = proplists:get_value(vsn, PropList), + ok. + +run(Dir) -> + run_save(Dir), + run_load(Dir), + ok. + +%% +%% Generate the contents of a simple .app file +%% +app(Name, Modules) -> + App = {application, Name, + [{description, atom_to_list(Name)}, + {vsn, git}, + {modules, Modules}, + {registered, []}, + {applications, [kernel, stdlib]}]}, + io_lib:format("~p.\n", [App]). + +vsn_cache_file(Name, Entries) -> + file:write_file(Name, + [io_lib:format("~p.~n", [X]) || X <- Entries]). diff --git a/src/rebar.erl b/src/rebar.erl index 888f80d..5a809d2 100644 --- a/src/rebar.erl +++ b/src/rebar.erl @@ -143,7 +143,7 @@ init_config({Options, _NonOptArgs}) -> %% Keep track of how many operations we do, so we can detect bad commands BaseConfig1 = rebar_config:set_xconf(BaseConfig, operations, 0), %% Initialize vsn cache - rebar_config:set_xconf(BaseConfig1, vsn_cache, dict:new()). + rebar_utils:init_vsn_cache(BaseConfig1). init_config1(BaseConfig) -> %% Determine the location of the rebar executable; important for pulling @@ -288,6 +288,7 @@ help() -> ?CONSOLE( "Environment variables:~n" " REBAR_DEPS_PREFER_LIBS to look for dependecies in system libs prior fetching.~n" + " REBAR_VSN_CACHE_FILE to load vsn cache from and save to specified file.~n" "~n", []). %% diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 0650430..6cc8d38 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -106,7 +106,7 @@ process_commands([Command | Rest], ParentConfig) -> ParentConfig2), %% Wipe out vsn cache to avoid invalid hits when %% dependencies are updated - rebar_config:set_xconf(ParentConfig3, vsn_cache, dict:new()) + rebar_utils:init_vsn_cache(ParentConfig3) catch throw:rebar_abort -> case rebar_config:get_xconf(ParentConfig1, keep_going, false) of diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 1fb5419..c3ebfe5 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -67,7 +67,9 @@ processing_base_dir/1, processing_base_dir/2, patch_env/2, - cleanup_code_path/1 + cleanup_code_path/1, + init_vsn_cache/1, + save_vsn_cache/1 ]). %% for internal use only @@ -268,6 +270,23 @@ expand_env_variable(InStr, VarName, RawVarValue) -> re:replace(InStr, RegEx, [VarValue, "\\2"], ReOpts) end. +init_vsn_cache(Config) -> + init_vsn_cache(Config, os:getenv("REBAR_VSN_CACHE_FILE")). +init_vsn_cache(Config, false) -> + rebar_config:set_xconf(Config, vsn_cache, dict:new()); +init_vsn_cache(Config, CacheFile) -> + {ok, CacheList} = file:consult(CacheFile), + CacheDict = dict:from_list(CacheList), + rebar_config:set_xconf(Config, vsn_cache, CacheDict). + +save_vsn_cache(Config) -> + save_vsn_cache(Config, os:getenv("REBAR_VSN_CACHE_FILE")). +save_vsn_cache(_Config, false) -> + ok; +save_vsn_cache(Config, CacheFile) -> + file:write_file(CacheFile, + [io_lib:format("~p.~n", [X]) || X <- dict:to_list(rebar_config:get_xconf(Config, vsn_cache))]). + vcs_vsn(Config, Vsn, Dir) -> Key = {Vsn, Dir}, Cache = rebar_config:get_xconf(Config, vsn_cache), @@ -276,6 +295,7 @@ vcs_vsn(Config, Vsn, Dir) -> VsnString = vcs_vsn_1(Vsn, Dir), Cache1 = dict:store(Key, VsnString, Cache), Config1 = rebar_config:set_xconf(Config, vsn_cache, Cache1), + save_vsn_cache(Config1), {Config1, VsnString}; {ok, VsnString} -> {Config, VsnString} |