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.

94 rivejä
3.2 KiB

  1. %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
  2. %% ex: ts=4 sw=4 et
  3. -module(rebar_prv_local_upgrade).
  4. -behaviour(provider).
  5. -export([init/1,
  6. do/1,
  7. format_error/1]).
  8. -include("rebar.hrl").
  9. -include_lib("providers/include/providers.hrl").
  10. -include_lib("kernel/include/file.hrl").
  11. -define(PROVIDER, upgrade).
  12. -define(NAMESPACE, unstable).
  13. -define(DEPS, []).
  14. %% ===================================================================
  15. %% Public API
  16. %% ===================================================================
  17. -spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
  18. init(State) ->
  19. State1 =
  20. rebar_state:add_provider(State,
  21. providers:create([{name, ?PROVIDER},
  22. {module, ?MODULE},
  23. {bare, true},
  24. {namespace, ?NAMESPACE},
  25. {deps, ?DEPS},
  26. {example, "rebar3 unstable upgrade"},
  27. {short_desc, "Download latest rebar3 escript and extract."},
  28. {desc, ""},
  29. {opts, []}])),
  30. {ok, State1}.
  31. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
  32. do(State) ->
  33. case os:type() of
  34. {win32, _} ->
  35. ?ERROR("Sorry, this feature is not yet available on Windows.", []),
  36. {ok, State};
  37. _ ->
  38. Md5 = case rebar_state:escript_path(State) of
  39. undefined ->
  40. false;
  41. ScriptPath ->
  42. get_md5(ScriptPath)
  43. end,
  44. case maybe_fetch_rebar3(Md5) of
  45. {saved, TmpRebar3} ->
  46. rebar_prv_local_install:extract_escript(State, TmpRebar3);
  47. up_to_date ->
  48. {ok, State};
  49. Error ->
  50. Error
  51. end
  52. end.
  53. -spec format_error(any()) -> iolist().
  54. format_error(bad_checksum) ->
  55. "Not updating rebar3, the checksum of download did not match the one provided by s3.";
  56. format_error(Reason) ->
  57. io_lib:format("~p", [Reason]).
  58. %% Internal
  59. get_md5(Rebar3Path) ->
  60. {ok, Rebar3File} = file:read_file(Rebar3Path),
  61. Digest = crypto:hash(md5, Rebar3File),
  62. DigestHex = lists:flatten([io_lib:format("~2.16.0B", [X]) || X <- binary_to_list(Digest)]),
  63. string:to_lower(DigestHex).
  64. maybe_fetch_rebar3(Rebar3Md5) ->
  65. TmpDir = ec_file:insecure_mkdtemp(),
  66. TmpFile = filename:join(TmpDir, "rebar3"),
  67. case rebar_pkg_resource:request("https://s3.amazonaws.com/rebar3/rebar3", Rebar3Md5) of
  68. {ok, Binary, ETag} ->
  69. file:write_file(TmpFile, Binary),
  70. case rebar_pkg_resource:etag(TmpFile) of
  71. ETag ->
  72. {saved, TmpFile};
  73. _ ->
  74. ?PRV_ERROR(bad_checksum)
  75. end;
  76. error ->
  77. ?ERROR("Unable to fetch latest rebar3 escript. Please try again later.", []);
  78. _ ->
  79. ?CONSOLE("No upgrade available", []),
  80. up_to_date
  81. end.