  @author   <  >
   ( C ) 2010 ,  
%%% @doc Ensure that the relatively-installed dependencies are on the code
%%%      loading path, and locate resources relative
%%%      to this application's path.
%%%
%%% @end
  Created :   8 Nov 2010 by   <  >

-module(whistle_couch_deps).
-author('author <>').

-export([ensure/0, ensure/1]).
-export([get_base_dir/0, get_base_dir/1]).
-export([local_path/1, local_path/2]).
-export([deps_on_path/0, new_siblings/1]).

    ( ) - > [ ProjNameAndVers ]
%% @doc List of project dependencies on the path.
deps_on_path() ->
    F = fun (X, Acc) ->
                ProjDir = filename:dirname(X),
                case {filename:basename(X),
                      filename:basename(filename:dirname(ProjDir))} of
                    {"ebin", "deps"} ->
                        [filename:basename(ProjDir) | Acc];
                    _ ->
                        Acc
                end
        end,
    ordsets:from_list(lists:foldl(F, [], code:get_path())).
    
    ) - > [ Dir ]
%% @doc Find new siblings paths relative to Module that aren't already on the
%%      code path.
new_siblings(Module) ->
    Existing = deps_on_path(),
    SiblingEbin = filelib:wildcard(local_path(["deps", "*", "ebin"], Module)),
    Siblings = [filename:dirname(X) || X <- SiblingEbin,
                           ordsets:is_element(
                             filename:basename(filename:dirname(X)),
                             Existing) =:= false],
    lists:filter(fun filelib:is_dir/1, 
                 lists:append([[filename:join([X, "ebin"]),
                                filename:join([X, "include"])] ||
                                  X <- Siblings])).
        

    ) - > ok
%% @doc Ensure that all ebin and include paths for dependencies
%%      of the application for Module are on the code path.
ensure(Module) ->
    code:add_pathsa(new_siblings(Module)),
    %% code:clash(),
    ok.

  @spec ensure ( ) - > ok
%% @doc Ensure that the ebin and include paths for dependencies of
%%      this application are on the code path. Equivalent to
%%      ensure(?Module).
ensure() ->
    ensure(?MODULE).

   get_base_dir(Module ) - > string ( )
%% @doc Return the application directory for Module. It assumes Module is in
       a standard OTP layout application in the ebin or src directory .
get_base_dir(Module) ->
    {file, Here} = code:is_loaded(Module),
    filename:dirname(filename:dirname(Here)).

    ( ) - > string ( )
%% @doc Return the application directory for this application. Equivalent to
%%      get_base_dir(?MODULE).
get_base_dir() ->
    get_base_dir(?MODULE).

    ( ) ] , Module ) - > string ( )
  @doc Return an application - relative directory from Module 's application .
local_path(Components, Module) ->
    filename:join([get_base_dir(Module) | Components]).

   local_path(Components ) - > string ( )
%% @doc Return an application-relative directory for this application.
%%      Equivalent to local_path(Components, ?MODULE).
local_path(Components) ->
    local_path(Components, ?MODULE).

 @doc Ensure that the relatively-installed dependencies are on the code
      loading path, and locate resources relative
      to this application's path.

 @end
 @doc List of project dependencies on the path.
 @doc Find new siblings paths relative to Module that aren't already on the
      code path.
 @doc Ensure that all ebin and include paths for dependencies
      of the application for Module are on the code path.
 code:clash(),
 @doc Ensure that the ebin and include paths for dependencies of
      this application are on the code path. Equivalent to
      ensure(?Module).
 @doc Return the application directory for Module. It assumes Module is in
 @doc Return the application directory for this application. Equivalent to
      get_base_dir(?MODULE).
 @doc Return an application-relative directory for this application.
      Equivalent to local_path(Components, ?MODULE).
  @author   <  >
   ( C ) 2010 ,  
  Created :   8 Nov 2010 by   <  >

-module(whistle_couch_deps).
-author('author <>').

-export([ensure/0, ensure/1]).
-export([get_base_dir/0, get_base_dir/1]).
-export([local_path/1, local_path/2]).
-export([deps_on_path/0, new_siblings/1]).

    ( ) - > [ ProjNameAndVers ]
deps_on_path() ->
    F = fun (X, Acc) ->
                ProjDir = filename:dirname(X),
                case {filename:basename(X),
                      filename:basename(filename:dirname(ProjDir))} of
                    {"ebin", "deps"} ->
                        [filename:basename(ProjDir) | Acc];
                    _ ->
                        Acc
                end
        end,
    ordsets:from_list(lists:foldl(F, [], code:get_path())).
    
    ) - > [ Dir ]
new_siblings(Module) ->
    Existing = deps_on_path(),
    SiblingEbin = filelib:wildcard(local_path(["deps", "*", "ebin"], Module)),
    Siblings = [filename:dirname(X) || X <- SiblingEbin,
                           ordsets:is_element(
                             filename:basename(filename:dirname(X)),
                             Existing) =:= false],
    lists:filter(fun filelib:is_dir/1, 
                 lists:append([[filename:join([X, "ebin"]),
                                filename:join([X, "include"])] ||
                                  X <- Siblings])).
        

    ) - > ok
ensure(Module) ->
    code:add_pathsa(new_siblings(Module)),
    ok.

  @spec ensure ( ) - > ok
ensure() ->
    ensure(?MODULE).

   get_base_dir(Module ) - > string ( )
       a standard OTP layout application in the ebin or src directory .
get_base_dir(Module) ->
    {file, Here} = code:is_loaded(Module),
    filename:dirname(filename:dirname(Here)).

    ( ) - > string ( )
get_base_dir() ->
    get_base_dir(?MODULE).

    ( ) ] , Module ) - > string ( )
  @doc Return an application - relative directory from Module 's application .
local_path(Components, Module) ->
    filename:join([get_base_dir(Module) | Components]).

   local_path(Components ) - > string ( )
local_path(Components) ->
    local_path(Components, ?MODULE).
