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

106 строки
4.5 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_update).
  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. -define(PROVIDER, update).
  11. -define(DEPS, []).
  12. %% ===================================================================
  13. %% Public API
  14. %% ===================================================================
  15. -spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
  16. init(State) ->
  17. State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
  18. {module, ?MODULE},
  19. {bare, false},
  20. {deps, ?DEPS},
  21. {example, "rebar3 update"},
  22. {short_desc, "Update package index."},
  23. {desc, "Update package index."},
  24. {opts, []}])),
  25. {ok, State1}.
  26. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
  27. do(State) ->
  28. ?INFO("Updating package index...", []),
  29. try
  30. Dir = rebar_dir:global_cache_dir(State),
  31. RegistryDir = filename:join(Dir, "packages"),
  32. filelib:ensure_dir(filename:join(RegistryDir, "dummy")),
  33. HexFile = filename:join(RegistryDir, "registry"),
  34. TmpDir = ec_file:insecure_mkdtemp(),
  35. TmpFile = filename:join(TmpDir, "packages.gz"),
  36. Url = rebar_state:get(State, rebar_packages_cdn, "https://s3.amazonaws.com/s3.hex.pm/registry.ets.gz"),
  37. {ok, _RequestId} = httpc:request(get, {Url, []},
  38. [], [{stream, TmpFile}, {sync, true}]),
  39. {ok, Data} = file:read_file(TmpFile),
  40. Unzipped = zlib:gunzip(Data),
  41. ok = file:write_file(HexFile, Unzipped),
  42. {Dict, Graph} = hex_to_graph(HexFile),
  43. write_registry(Dict, Graph, State),
  44. ok
  45. catch
  46. _E:_C ->
  47. throw(?PRV_ERROR(package_index_write))
  48. end,
  49. {ok, State}.
  50. -spec format_error(any()) -> iolist().
  51. format_error(package_index_write) ->
  52. "Failed to write package index.".
  53. write_registry(Dict, {digraph, Edges, Vertices, Neighbors, _}, State) ->
  54. Dir = rebar_dir:global_cache_dir(State),
  55. RegistryDir = filename:join(Dir, "packages"),
  56. filelib:ensure_dir(filename:join(RegistryDir, "dummy")),
  57. ets:tab2file(Edges, filename:join(RegistryDir, "edges")),
  58. ets:tab2file(Vertices, filename:join(RegistryDir, "vertices")),
  59. ets:tab2file(Neighbors, filename:join(RegistryDir, "neighbors")),
  60. file:write_file(filename:join(RegistryDir, "dict"), term_to_binary(Dict)).
  61. hex_to_graph(Filename) ->
  62. {ok, T} = ets:file2tab(Filename),
  63. Graph = digraph:new(),
  64. ets:foldl(fun({Pkg, [Versions]}, ok) when is_binary(Pkg), is_list(Versions) ->
  65. lists:foreach(fun(Version) ->
  66. digraph:add_vertex(Graph, {Pkg, Version}, 1)
  67. end, Versions);
  68. (_, ok) ->
  69. ok
  70. end, ok, T),
  71. Dict1 = ets:foldl(fun({{Pkg, PkgVsn}, [Deps | _]}, Dict) ->
  72. DepsList = update_graph(Pkg, PkgVsn, Deps, T, Graph),
  73. dict:store({Pkg, PkgVsn}, DepsList, Dict);
  74. (_, Dict) ->
  75. Dict
  76. end, dict:new(), T),
  77. {Dict1, Graph}.
  78. update_graph(Pkg, PkgVsn, Deps, HexRegistry, Graph) ->
  79. lists:foldl(fun([Dep, DepVsn, false, _AppName | _], DepsListAcc) ->
  80. case DepVsn of
  81. <<"~> ", Vsn/binary>> ->
  82. HighestDepVsn = rebar_packages:find_highest_matching(Dep, Vsn, HexRegistry),
  83. digraph:add_edge(Graph, {Pkg, PkgVsn}, {Dep, HighestDepVsn}),
  84. [{Dep, DepVsn} | DepsListAcc];
  85. Vsn ->
  86. digraph:add_edge(Graph, {Pkg, PkgVsn}, {Dep, Vsn}),
  87. [{Dep, Vsn} | DepsListAcc]
  88. end;
  89. ([_Dep, _DepVsn, true, _AppName | _], DepsListAcc) ->
  90. DepsListAcc
  91. end, [], Deps).