Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

108 строки
4.3 KiB

10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
  1. %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
  2. %% ex: ts=4 sw=4 et
  3. -module(rebar_prv_as).
  4. -behaviour(provider).
  5. -export([init/1,
  6. do/1,
  7. format_error/1]).
  8. -include("rebar.hrl").
  9. -define(PROVIDER, as).
  10. -define(DEPS, []).
  11. %% ===================================================================
  12. %% Public API
  13. %% ===================================================================
  14. -spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
  15. init(State) ->
  16. State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
  17. {module, ?MODULE},
  18. {bare, true},
  19. {deps, ?DEPS},
  20. {example, "rebar3 as <profile1>,<profile2>,... <task1>, <task2>, ..."},
  21. {short_desc, "Higher order provider for running multiple tasks in a sequence as a certain profiles."},
  22. {desc, "Higher order provider for running multiple tasks in a sequence as a certain profiles."},
  23. {opts, [{profile, undefined, undefined, string, "Profiles to run as."}]}])),
  24. {ok, State1}.
  25. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
  26. do(State) ->
  27. {Profiles, Tasks} = args_to_profiles_and_tasks(rebar_state:command_args(State)),
  28. case {Profiles, Tasks} of
  29. {[], _} ->
  30. {error, "At least one profile must be specified when using `as`"};
  31. {_, []} ->
  32. {error, "At least one task must be specified when using `as`"};
  33. _ ->
  34. warn_on_empty_profile(Profiles, State),
  35. State1 = rebar_state:apply_profiles(State, [list_to_atom(X) || X <- Profiles]),
  36. State2 = rebar_plugins:project_apps_install(State1),
  37. {FirstTask, FirstTaskArgs} = hd(Tasks),
  38. FirstTaskAtom = list_to_atom(FirstTask),
  39. case rebar_core:process_namespace(State2, FirstTaskAtom) of
  40. {ok, State3, NewTask} ->
  41. rebar_prv_do:do_tasks(
  42. [{atom_to_list(NewTask),FirstTaskArgs}|tl(Tasks)],
  43. State3
  44. );
  45. {error, Reason} ->
  46. {error, Reason}
  47. end
  48. end.
  49. -spec format_error(any()) -> iolist().
  50. format_error(Reason) ->
  51. io_lib:format("~p", [Reason]).
  52. args_to_profiles_and_tasks(Args) ->
  53. first_profile(Args).
  54. first_profile([]) -> {[], []};
  55. first_profile([ProfileList|Rest]) ->
  56. case re:split(ProfileList, ",", [{return, list}, {parts, 2}, unicode]) of
  57. %% `foo, bar`
  58. [P, ""] -> profiles(Rest, [P]);
  59. %% `foo,bar`
  60. [P, More] -> profiles([More] ++ Rest, [P]);
  61. %% `foo`
  62. [P] -> comma_or_end(Rest, [P])
  63. end.
  64. profiles([], Acc) -> {lists:reverse(Acc), rebar_utils:args_to_tasks([])};
  65. profiles([ProfileList|Rest], Acc) ->
  66. case re:split(ProfileList, ",", [{return, list}, {parts, 2}, unicode]) of
  67. %% `foo, bar`
  68. [P, ""] -> profiles(Rest, [P|Acc]);
  69. %% `foo,bar`
  70. [P, More] -> profiles([More] ++ Rest, [P|Acc]);
  71. %% `foo`
  72. [P] -> comma_or_end(Rest, [P|Acc])
  73. end.
  74. %% `, foo...`
  75. comma_or_end([","|Rest], Acc) ->
  76. profiles(Rest, Acc);
  77. %% `,foo...`
  78. comma_or_end(["," ++ Profile|Rest], Acc) ->
  79. profiles([Profile|Rest], Acc);
  80. comma_or_end(Tasks, Acc) ->
  81. {lists:reverse(Acc), rebar_utils:args_to_tasks(Tasks)}.
  82. %% If a profile is used by 'as' but has no entry under `profile` within
  83. %% the top level rebar.config or any project app's rebar.config print a warning.
  84. %% This is just to help developers, in case they forgot to define a profile but
  85. %% thought it was being used.
  86. warn_on_empty_profile(Profiles, State) ->
  87. ProjectApps = rebar_state:project_apps(State),
  88. DefinedProfiles = rebar_state:get(State, profiles, []) ++
  89. lists:flatten([rebar_app_info:get(AppInfo, profiles, []) || AppInfo <- ProjectApps]),
  90. [?WARN("No entry for profile ~ts in config.", [Profile])
  91. || Profile <- Profiles,
  92. not lists:keymember(list_to_atom(Profile), 1, DefinedProfiles),
  93. Profile =/= "global", Profile =/= "default"],
  94. ok.