Skip to content

Commit

Permalink
Enhance rebar.config.script for dev only dependencies
Browse files Browse the repository at this point in the history
ibrowse and meck are only used for testing and should not be imposed
as dependencies on projects using webmachine.

rebar.config.script is used to support a dev_only_deps key in
rebar.config. The mechanism is triggered by a marker file DEV_MODE
written to the top-level of the project directory. If found, the
dev_only_deps are merged into deps. The project's Makefile is modified
to create the DEV_MODE file. Those doing dev work on webmachine can
continue to run builds via standard make commands. Projects pulling in
a dep on webmachine via rebar will receive just the needed bits.
  • Loading branch information
Seth Falcon authored and kellymclaughlin committed Dec 8, 2014
1 parent dac718b commit a907e90
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 21 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ deps/*
ebin/*.app
doc/*
.local_dialyzer_plt
/.rebar
12 changes: 9 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ all: deps compile
compile: deps
./rebar compile

deps:
deps: DEV_MODE
@(./rebar get-deps)

clean:
@(./rebar clean)

distclean: clean
@(./rebar delete-deps)
# nuke deps first to avoid wasting time having rebar recurse into deps
# for clean
distclean:
@rm -rf deps ./rebar/DEV_MODE
@(./rebar clean)

edoc:
@$(ERL) -noshell -run edoc_run application '$(APP)' '"."' '[{preprocess, true},{includes, ["."]}]'
Expand All @@ -34,3 +37,6 @@ verbosetest: all
travisupload:
tar cvfz ${ARTIFACTSFILE} --exclude '*.beam' --exclude '*.erl' test.log .eunit
travis-artifacts upload --path ${ARTIFACTSFILE}

DEV_MODE:
@touch ./.rebar/DEV_MODE
9 changes: 6 additions & 3 deletions rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
{xref_checks, [undefined_function_calls]}.

{deps,
[{mochiweb, "2.9.0", {git, "git://github.com/basho/mochiweb.git", {tag, "v2.9.0"}}},
{meck, "0.8.2", {git, "git://github.com/basho/meck.git", {tag, "0.8.2"}}},
{ibrowse, "4.0.*", {git, "git://github.com/cmullaparthi/ibrowse.git", {tag, "v4.0.2"}}}
[{mochiweb, "2.9.0", {git, "git://github.com/basho/mochiweb.git", {tag, "v2.9.0"}}}
]}.

{dev_only_deps,
[{meck, "0.8.2", {git, "git://github.com/basho/meck.git", {tag, "0.8.2"}}},
{ibrowse, "4.0.2", {git, "git://github.com/cmullaparthi/ibrowse.git", {tag, "v4.0.2"}}}
]}.
79 changes: 64 additions & 15 deletions rebar.config.script
Original file line number Diff line number Diff line change
@@ -1,19 +1,68 @@
%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
%% ex: ft=erlang ts=4 sw=4 et
OtpVersion = erlang:system_info(otp_release),
Config1 = case hd(OtpVersion) =:= $R andalso OtpVersion =< "R15B01" of
true ->
HashDefine = [{d,old_hash}],
case lists:keysearch(erl_opts, 1, CONFIG) of
{value, {erl_opts, Opts}} ->
lists:keyreplace(erl_opts,1,CONFIG,{erl_opts,Opts++HashDefine});
false ->
CONFIG ++ [{erl_opts, HashDefine}]
end;
false -> CONFIG
end.

case erlang:system_info(otp_release) of
"R"++_=RVersion ->
case RVersion =< "R15B01" of
true ->
HashDefine = [{d,old_hash}],
case lists:keysearch(erl_opts, 1, CONFIG) of
{value, {erl_opts, Opts}} ->
lists:keyreplace(erl_opts,1,CONFIG,{erl_opts,Opts++HashDefine});
false ->
CONFIG ++ [{erl_opts, HashDefine}]
end;
false -> CONFIG
end;
_ ->
CONFIG
%% Merge the list values in `ToAdd' into the list found at key `Key'
%% in proplist `C'. Don't duplicate items. New Items are added to the
%% front of existing items. It is an error if the value at `Key' is
%% not a list in `C'.
MergeConfig = fun({Key, ToAdd}, C) ->
case lists:keyfind(Key, 1, C) of
false ->
lists:keystore(Key, 1, C, {Key, ToAdd});
{Key, List} when is_list(List) ->
%% remove items in ToAdd already in List
ToAdd1 = [ I || I <- ToAdd, not lists:member(I, List) ],
lists:keystore(Key, 1, C, {Key, ToAdd1 ++ List })
end
end.

%% -- Add development only options if we are a top-level build --
%%
%% If a file named `./.rebar/DEV_MODE' exists, we assume we are a
%% top-level build (not being built as a dep of another project). We
%% add the deps from dev_only_deps defined in rebar.config, add
%% concrete as a dep, and define the compiler macro DEV_ONLY.

%% This macro can be used to conditionally enable code (e.g. tests)
%% that depend on development only dependencies.
ErlOpts = {erl_opts, [
{d, 'DEV_ONLY'}
]},

%% Development only dependencies can be specified in the main
%% rebar.config. This file should not need to be edited directly.
DevOnlyDeps = case lists:keyfind(dev_only_deps, 1, CONFIG) of
false ->
[];
{dev_only_deps, DOD} ->
DOD
end,

Deps = {deps, DevOnlyDeps},

ConfigPath = filename:dirname(SCRIPT),
DevMarker = filename:join([ConfigPath, ".rebar", "DEV_MODE"]),
_ = filelib:ensure_dir(DevMarker),
case filelib:is_file(DevMarker) of
true ->
lists:foldl(fun(I, C) -> MergeConfig(I, C) end,
Config1, [Deps, ErlOpts]);
false ->
%% If the ./.rebar/DEV_MODE marker is not present, this script simply
%% returns the config specified in rebar.config. This will be
%% the behavior when the project is built as a dependency of
%% another project.
Config1
end.

0 comments on commit a907e90

Please sign in to comment.