Skip to content

Instantly share code, notes, and snippets.

@00-matt
Last active March 27, 2021 10:11
Show Gist options
  • Save 00-matt/5287ec6ea5c7e6e97306b91612dd5615 to your computer and use it in GitHub Desktop.
Save 00-matt/5287ec6ea5c7e6e97306b91612dd5615 to your computer and use it in GitHub Desktop.
#!/usr/bin/env escript
% -*- erlang -*-
%
% Copyright 1999-2021 Gentoo Authors
% Distributed under the terms of the GNU General Public License v2
%
% A small script to generate the ETS table that represents Rebar 3's
% package cache.
-module(gen_package_index).
-type ms_field() :: '$1' | '_' | {'$1', '$2'}.
-record(package, {key :: {unicode:unicode_binary() | ms_field(), unicode:unicode_binary() | ms_field() | ec_semver:semver(),
unicode:unicode_binary() | ms_field()},
inner_checksum :: binary() | ms_field(),
outer_checksum :: binary() | ms_field(),
retired :: boolean() | ms_field() | #{reason := atom()},
dependencies :: [#{package => unicode:unicode_binary(),
requirement => unicode:unicode_binary()}] | ms_field()}).
main([Filename]) ->
Tab = ets:new(package_index,
[named_table, public, ordered_set, {keypos, 2}]),
ets:insert(Tab, {6, package_index_version}),
Deps = read_deps(),
process_deps(Tab, Deps),
ok = ets:tab2file(Tab, Filename);
main(_) ->
usage().
process_deps(_Tab, []) ->
ok;
process_deps(Tab, [{Name, Version, Tarball}|Deps]) ->
{OuterChecksum, InnerChecksum} = checksum(Tarball),
io:format("~s ~w~n~s~n~s~n~n", [Name, Version, InnerChecksum, OuterChecksum]),
ets:insert(Tab, #package{key={Name, {Version, {[], []}}, "hexpm"},
inner_checksum=InnerChecksum,
outer_checksum=OuterChecksum,
retired=false,
dependencies=[]}),
process_deps(Tab, Deps).
checksum(OuterFile) ->
{ok, OuterContents} = file:read_file(OuterFile),
OuterChecksumBinary = crypto:hash(sha256, OuterContents),
OuterChecksum = io_lib:format("~s", [[io_lib:format("~2.16.0B",[X]) || <<X:8>> <= OuterChecksumBinary ]]),
{ok, [{"CHECKSUM", InnerChecksum}]} = erl_tar:extract({binary, OuterContents}, [memory, {files, ["CHECKSUM"]}]),
{OuterChecksum, InnerChecksum}.
read_deps() ->
read_deps([]).
read_deps(Deps) ->
case io:get_line("") of
eof ->
Deps;
Line ->
{match, [Name, Major, Minor, Patch]} = re:run(Line,
"(\\w+)-(\\d+)\.(\\d+)\.(\\d+)",
[{capture, all_but_first, list}]),
{MajorInt, _} = string:to_integer(Major),
{MinorInt, _} = string:to_integer(Minor),
{PatchInt, _} = string:to_integer(Patch),
OuterFile = io_lib:format("/var/cache/distfiles/~s-~w.~w.~w.hex.tar", [Name, MajorInt, MinorInt, PatchInt]),
read_deps([{Name, {MajorInt, MinorInt, PatchInt}, OuterFile}|Deps])
end.
usage() ->
io:format("usage: gen_package_index <file>\n"),
halt(1).
===> Verifying dependencies...
===> Failed to update package bbmustache from repo hexpm
escript: exception error: no match of right hand side value
{error,
{rebar_app_utils,
{missing_package,<<"bbmustache">>,<<"1.10.0">>}}}
in function erl_eval:expr/5 (erl_eval.erl, line 453)
in call from escript:eval_exprs/5 (escript.erl, line 872)
in call from erl_eval:local_func/6 (erl_eval.erl, line 567)
in call from escript:interpret/4 (escript.erl, line 788)
in call from escript:start/1 (escript.erl, line 277)
in call from init:start_em/1
in call from init:do_boot/3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment