|
| 1 | +%%% -*- erlang -*- |
| 2 | +%%% |
| 3 | +%%% This file is part of barrel released under the MIT license. |
| 4 | +%%% See the NOTICE for more information. |
| 5 | + |
| 6 | +-module(barrel_deps). |
| 7 | +-author('Justin Sheehy <justin@basho.com>'). |
| 8 | +-author('Andy Gross <andy@basho.com>'). |
| 9 | + |
| 10 | +-export([ensure/0, ensure/1]). |
| 11 | +-export([get_base_dir/0, get_base_dir/1]). |
| 12 | +-export([local_path/1, local_path/2]). |
| 13 | +-export([deps_on_path/0, new_siblings/1]). |
| 14 | + |
| 15 | +%% @spec deps_on_path() -> [ProjNameAndVers] |
| 16 | +%% @doc List of project dependencies on the path. |
| 17 | +deps_on_path() -> |
| 18 | + ordsets:from_list([filename:basename(filename:dirname(X)) || X <- code:get_path()]). |
| 19 | + |
| 20 | +%% @spec new_siblings(Module) -> [Dir] |
| 21 | +%% @doc Find new siblings paths relative to Module that aren't already on the |
| 22 | +%% code path. |
| 23 | +new_siblings(Module) -> |
| 24 | + Existing = deps_on_path(), |
| 25 | + SiblingEbin = [ X || X <- filelib:wildcard(local_path(["deps", "*", "ebin"], Module)), |
| 26 | + filename:basename(filename:dirname(X)) /= %% don't include self |
| 27 | + filename:basename(filename:dirname( |
| 28 | + filename:dirname( |
| 29 | + filename:dirname(X)))) ], |
| 30 | + Siblings = [filename:dirname(X) || X <- SiblingEbin, |
| 31 | + ordsets:is_element( |
| 32 | + filename:basename(filename:dirname(X)), |
| 33 | + Existing) =:= false], |
| 34 | + lists:filter(fun filelib:is_dir/1, |
| 35 | + lists:append([[filename:join([X, "ebin"]), |
| 36 | + filename:join([X, "include"])] || |
| 37 | + X <- Siblings])). |
| 38 | + |
| 39 | + |
| 40 | +%% @spec ensure(Module) -> ok |
| 41 | +%% @doc Ensure that all ebin and include paths for dependencies |
| 42 | +%% of the application for Module are on the code path. |
| 43 | +ensure(Module) -> |
| 44 | + code:add_paths(new_siblings(Module)), |
| 45 | + %% code:clash is annoying when you load couchbeam in a script. |
| 46 | + %% code:clash(), |
| 47 | + ok. |
| 48 | + |
| 49 | +%% @spec ensure() -> ok |
| 50 | +%% @doc Ensure that the ebin and include paths for dependencies of |
| 51 | +%% this application are on the code path. Equivalent to |
| 52 | +%% ensure(?Module). |
| 53 | +ensure() -> |
| 54 | + ensure(?MODULE). |
| 55 | + |
| 56 | +%% @spec get_base_dir(Module) -> string() |
| 57 | +%% @doc Return the application directory for Module. It assumes Module is in |
| 58 | +%% a standard OTP layout application in the ebin or src directory. |
| 59 | +get_base_dir(Module) -> |
| 60 | + {file, Here} = code:is_loaded(Module), |
| 61 | + filename:dirname(filename:dirname(Here)). |
| 62 | + |
| 63 | +%% @spec get_base_dir() -> string() |
| 64 | +%% @doc Return the application directory for this application. Equivalent to |
| 65 | +%% get_base_dir(?MODULE). |
| 66 | +get_base_dir() -> |
| 67 | + get_base_dir(?MODULE). |
| 68 | + |
| 69 | +%% @spec local_path([string()], Module) -> string() |
| 70 | +%% @doc Return an application-relative directory from Module's application. |
| 71 | +local_path(Components, Module) -> |
| 72 | + filename:join([get_base_dir(Module) | Components]). |
| 73 | + |
| 74 | +%% @spec local_path(Components) -> string() |
| 75 | +%% @doc Return an application-relative directory for this application. |
| 76 | +%% Equivalent to local_path(Components, ?MODULE). |
| 77 | +local_path(Components) -> |
| 78 | + local_path(Components, ?MODULE). |
0 commit comments