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.

104 lines
4.2 KiB

  1. -module(rebar_prv_packages).
  2. -behaviour(provider).
  3. -export([init/1,
  4. do/1,
  5. format_error/1]).
  6. -include("rebar.hrl").
  7. -include_lib("stdlib/include/ms_transform.hrl").
  8. -include_lib("providers/include/providers.hrl").
  9. -define(PROVIDER, pkgs).
  10. -define(DEPS, []).
  11. -spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
  12. init(State) ->
  13. State1 = rebar_state:add_provider(State,
  14. providers:create([{name, ?PROVIDER},
  15. {module, ?MODULE},
  16. {bare, true},
  17. {deps, ?DEPS},
  18. {example, "rebar3 pkgs elli"},
  19. {short_desc, "List information for a package."},
  20. {desc, info("List information for a package")},
  21. {opts, [{package, undefined, undefined, string,
  22. "Package to fetch information for."}]}])),
  23. {ok, State1}.
  24. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
  25. do(State) ->
  26. {Args, _} = rebar_state:command_parsed_args(State),
  27. case proplists:get_value(package, Args, undefined) of
  28. undefined ->
  29. ?PRV_ERROR(no_package_arg);
  30. Name ->
  31. Resources = rebar_state:resources(State),
  32. #{repos := Repos} = rebar_resource_v2:find_resource_state(pkg, Resources),
  33. Results = get_package(rebar_utils:to_binary(Name), Repos),
  34. case lists:all(fun({_, {error, not_found}}) -> true; (_) -> false end, Results) of
  35. true ->
  36. ?PRV_ERROR({not_found, Name});
  37. false ->
  38. [print_packages(Result) || Result <- Results],
  39. {ok, State}
  40. end
  41. end.
  42. -spec get_package(binary(), [map()]) -> [{binary(), {ok, map()} | {error, term()}}].
  43. get_package(Name, Repos) ->
  44. lists:foldl(fun(RepoConfig, Acc) ->
  45. [{maps:get(name, RepoConfig), rebar_packages:get(RepoConfig, Name)} | Acc]
  46. end, [], Repos).
  47. -spec format_error(any()) -> iolist().
  48. format_error(no_package_arg) ->
  49. "Missing package argument to `rebar3 pkgs` command.";
  50. format_error({not_found, Name}) ->
  51. io_lib:format("Package ~ts not found in any repo.", [Name]);
  52. format_error(unknown) ->
  53. "Something went wrong with fetching package metadata.".
  54. print_packages({RepoName, {error, not_found}}) ->
  55. ?CONSOLE("~ts: Package not found in this repo.~n", [RepoName]);
  56. print_packages({RepoName, {error, _}}) ->
  57. ?CONSOLE("~ts: Error fetching from this repo.~n", [RepoName]);
  58. print_packages({RepoName, {ok, #{<<"name">> := Name,
  59. <<"meta">> := Meta,
  60. <<"releases">> := Releases}}}) ->
  61. Description = maps:get(<<"description">>, Meta, ""),
  62. Licenses = join(maps:get(<<"licenses">>, Meta, []), <<", ">>),
  63. Links = join_map(maps:get(<<"links">>, Meta, []), <<"\n ">>),
  64. Maintainers = join(maps:get(<<"maintainers">>, Meta, []), <<", ">>),
  65. Versions = [V || #{<<"version">> := V} <- Releases],
  66. VsnStr = join(Versions, <<", ">>),
  67. ?CONSOLE("~ts:~n"
  68. " Name: ~ts~n"
  69. " Description: ~ts~n"
  70. " Licenses: ~ts~n"
  71. " Maintainers: ~ts~n"
  72. " Links:~n ~ts~n"
  73. " Versions: ~ts~n", [RepoName, Name, Description, Licenses, Maintainers, Links, VsnStr]);
  74. print_packages(_) ->
  75. ok.
  76. -spec join([binary()], binary()) -> binary().
  77. join([Bin], _Sep) ->
  78. <<Bin/binary>>;
  79. join([Bin | T], Sep) ->
  80. <<Bin/binary, Sep/binary, (join(T, Sep))/binary>>.
  81. -spec join_map(map(), binary()) -> binary().
  82. join_map(Map, Sep) ->
  83. join_tuple_list(maps:to_list(Map), Sep).
  84. join_tuple_list([{K, V}], _Sep) ->
  85. <<K/binary, ": ", V/binary>>;
  86. join_tuple_list([{K, V} | T], Sep) ->
  87. <<K/binary, ": ", V/binary, Sep/binary, (join_tuple_list(T, Sep))/binary>>.
  88. info(Description) ->
  89. io_lib:format("~ts.~n", [Description]).