You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
3.0 KiB

  1. %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
  2. %% ex: ts=4 sw=4 et
  3. -module(rebar_relx).
  4. -export([do/4,
  5. format_error/1]).
  6. -include("rebar.hrl").
  7. %% ===================================================================
  8. %% Public API
  9. %% ===================================================================
  10. -spec do(atom(), string(), atom(), rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
  11. do(Module, Command, Provider, State) ->
  12. Options = rebar_state:command_args(State),
  13. DepsDir = rebar_dir:deps_dir(State),
  14. ProjectAppDirs = lists:delete(".", ?DEFAULT_PROJECT_APP_DIRS),
  15. LibDirs = rebar_utils:filtermap(fun ec_file:exists/1,
  16. [?DEFAULT_CHECKOUTS_DIR, DepsDir | ProjectAppDirs]),
  17. OutputDir = filename:join(rebar_dir:base_dir(State), ?DEFAULT_RELEASE_DIR),
  18. AllOptions = string:join([Command | Options], " "),
  19. Cwd = rebar_state:dir(State),
  20. Providers = rebar_state:providers(State),
  21. rebar_hooks:run_all_hooks(Cwd, pre, Provider, Providers, State),
  22. try
  23. case rebar_state:get(State, relx, []) of
  24. [] ->
  25. relx:main([{lib_dirs, LibDirs}
  26. ,{caller, api} | output_dir(OutputDir, Options)], AllOptions);
  27. Config ->
  28. Config1 = update_config(Config),
  29. relx:main([{lib_dirs, LibDirs}
  30. ,{config, Config1}
  31. ,{caller, api} | output_dir(OutputDir, Options)], AllOptions)
  32. end,
  33. rebar_hooks:run_all_hooks(Cwd, post, Provider, Providers, State),
  34. {ok, State}
  35. catch
  36. throw:T ->
  37. {error, {Module, T}}
  38. end.
  39. -spec format_error(any()) -> iolist().
  40. format_error(Reason) ->
  41. io_lib:format("~p", [Reason]).
  42. %% To handle profiles rebar3 expects the provider to use the first entry
  43. %% in a configuration key-value list as the value of a key if dups exist.
  44. %% This does not work with relx. Some config options must not lose their
  45. %% order (release which has an extends option is one). So here we pull out
  46. %% options that are special so we can reverse the rest so what we expect
  47. %% from a rebar3 profile is what we get on the relx side.
  48. -define(SPECIAL_KEYS, [release, vm_args, sys_config, overlay_vars, lib_dirs]).
  49. update_config(Config) ->
  50. {Special, Other} =
  51. lists:foldl(fun(Tuple, {SpecialAcc, OtherAcc}) when is_tuple(Tuple) ->
  52. case lists:member(element(1, Tuple), ?SPECIAL_KEYS) of
  53. true ->
  54. {[Tuple | SpecialAcc], OtherAcc};
  55. false ->
  56. {SpecialAcc, [Tuple | OtherAcc]}
  57. end
  58. end, {[], []}, Config),
  59. lists:reverse(Special) ++ Other.
  60. %% Don't override output_dir if the user passed one on the command line
  61. output_dir(OutputDir, Options) ->
  62. [{output_dir, OutputDir} || not(lists:member("-o", Options))
  63. andalso not(lists:member("--output-dir", Options))].