Compare commits
6 Commits
2b24b17af3
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| eecff86500 | |||
| 2ac9363d30 | |||
| 4698b54832 | |||
| 4cc6adee2e | |||
| 4f97dd1bd1 | |||
| 05bbf058be |
@@ -1,6 +1,6 @@
|
|||||||
{application,gmserialization,
|
{application,gmserialization,
|
||||||
[{description,"Serialization of data for the Gajumaru"},
|
[{description,"Serialization of data for the Gajumaru"},
|
||||||
{vsn,"0.1.2"},
|
{vsn,"0.2.0"},
|
||||||
{registered,[]},
|
{registered,[]},
|
||||||
{applications,[kernel,stdlib,crypto,base58]},
|
{applications,[kernel,stdlib,crypto,base58]},
|
||||||
{env,[]},
|
{env,[]},
|
||||||
|
|||||||
@@ -6,14 +6,20 @@
|
|||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(gmser_api_encoder).
|
-module(gmser_api_encoder).
|
||||||
-vsn("0.1.2").
|
-vsn("0.2.0").
|
||||||
|
|
||||||
-export([encode/2,
|
-export([encode/2,
|
||||||
decode/1,
|
decode/1,
|
||||||
safe_decode/2,
|
safe_decode/2,
|
||||||
byte_size_for_type/1]).
|
byte_size_for_type/1]).
|
||||||
|
|
||||||
-export_type([encoded/0]).
|
-export([encode_keypair/1,
|
||||||
|
safe_decode_keypair/1]).
|
||||||
|
|
||||||
|
-export([unsafe_encode/2]). %% Encode without size checks
|
||||||
|
|
||||||
|
-export_type([encoded/0,
|
||||||
|
known_type/0]).
|
||||||
|
|
||||||
-type known_type() :: key_block_hash
|
-type known_type() :: key_block_hash
|
||||||
| micro_block_hash
|
| micro_block_hash
|
||||||
@@ -38,6 +44,7 @@
|
|||||||
| native_token
|
| native_token
|
||||||
| commitment
|
| commitment
|
||||||
| peer_pubkey
|
| peer_pubkey
|
||||||
|
| hash
|
||||||
| state
|
| state
|
||||||
| poi
|
| poi
|
||||||
| state_trees
|
| state_trees
|
||||||
@@ -51,14 +58,66 @@
|
|||||||
-type payload() :: binary().
|
-type payload() :: binary().
|
||||||
-type encoded() :: binary().
|
-type encoded() :: binary().
|
||||||
|
|
||||||
|
-type keypair() :: #{public := <<_:(32*8)>>, secret := <<_:(64*8)>>}.
|
||||||
|
-type encoded_keypair() :: #{binary() => binary()}.
|
||||||
|
|
||||||
|
-export_type([ keypair/0
|
||||||
|
, encoded_keypair/0 ]).
|
||||||
|
|
||||||
-define(BASE58, 1).
|
-define(BASE58, 1).
|
||||||
-define(BASE64, 2).
|
-define(BASE64, 2).
|
||||||
|
|
||||||
|
-spec encode_keypair(keypair()) -> encoded_keypair().
|
||||||
|
encode_keypair(#{public := Pub, secret := Sec}) ->
|
||||||
|
case Sec of
|
||||||
|
<<Seed:32/binary, Pub1:32/binary>> when Pub1 =:= Pub ->
|
||||||
|
#{ <<"pub">> => encode(account_pubkey, Pub)
|
||||||
|
, <<"priv">> => encode(account_seckey, Seed) };
|
||||||
|
_ ->
|
||||||
|
erlang:error(invalid_keypair)
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec safe_decode_keypair(encoded_keypair()) -> {'ok', keypair()} | {'error', atom()}.
|
||||||
|
safe_decode_keypair(#{<<"pub">> := EncPub, <<"priv">> := EncPriv}) ->
|
||||||
|
case safe_decode(account_pubkey, EncPub) of
|
||||||
|
{ok, Pub} ->
|
||||||
|
case safe_decode(account_seckey, EncPriv) of
|
||||||
|
{ok, Seed} when byte_size(Seed) =:= 32 ->
|
||||||
|
case enacl:sign_seed_keypair(Seed) of
|
||||||
|
#{public := Pub, secret := _} = KP ->
|
||||||
|
{ok, KP};
|
||||||
|
_ ->
|
||||||
|
{error, illegal_encoding}
|
||||||
|
end;
|
||||||
|
{ok, <<Seed:32/binary, Pub:32/binary>>} ->
|
||||||
|
case enacl:sign_seed_keypair(Seed) of
|
||||||
|
#{public := Pub} = KP ->
|
||||||
|
{ok, KP};
|
||||||
|
_ ->
|
||||||
|
{error, illegal_encoding}
|
||||||
|
end;
|
||||||
|
{ok, _} ->
|
||||||
|
{error, illegal_encoding};
|
||||||
|
{error, _} = Error1 ->
|
||||||
|
Error1
|
||||||
|
end;
|
||||||
|
Error ->
|
||||||
|
Error
|
||||||
|
end.
|
||||||
|
|
||||||
-spec encode(known_type(), payload() | gmser_id:id()) -> encoded().
|
-spec encode(known_type(), payload() | gmser_id:id()) -> encoded().
|
||||||
encode(id_hash, Payload) ->
|
encode(id_hash, Payload) ->
|
||||||
{IdType, Val} = gmser_id:specialize(Payload),
|
{IdType, Val} = gmser_id:specialize(Payload),
|
||||||
encode(id2type(IdType), Val);
|
encode(id2type(IdType), Val);
|
||||||
encode(Type, Payload) ->
|
encode(Type, Payload) ->
|
||||||
|
case type_size_check(Type, Payload) of
|
||||||
|
ok ->
|
||||||
|
unsafe_encode(Type, Payload);
|
||||||
|
{error, Reason} ->
|
||||||
|
erlang:error(Reason)
|
||||||
|
end.
|
||||||
|
|
||||||
|
unsafe_encode(Type, Payload) ->
|
||||||
Pfx = type2pfx(Type),
|
Pfx = type2pfx(Type),
|
||||||
Enc = case type2enc(Type) of
|
Enc = case type2enc(Type) of
|
||||||
?BASE58 -> base58_check(Payload);
|
?BASE58 -> base58_check(Payload);
|
||||||
@@ -66,6 +125,7 @@ encode(Type, Payload) ->
|
|||||||
end,
|
end,
|
||||||
<<Pfx/binary, "_", Enc/binary>>.
|
<<Pfx/binary, "_", Enc/binary>>.
|
||||||
|
|
||||||
|
|
||||||
-spec decode(binary()) -> {known_type(), payload()}.
|
-spec decode(binary()) -> {known_type(), payload()}.
|
||||||
decode(Bin0) ->
|
decode(Bin0) ->
|
||||||
case split(Bin0) of
|
case split(Bin0) of
|
||||||
@@ -81,6 +141,13 @@ decode(Bin0) ->
|
|||||||
erlang:error(missing_prefix)
|
erlang:error(missing_prefix)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
type_size_check(account_seckey, Bin) ->
|
||||||
|
case byte_size(Bin) of
|
||||||
|
Sz when Sz =:= 32; Sz =:= 64 ->
|
||||||
|
ok;
|
||||||
|
_ ->
|
||||||
|
{error, incorrect_size}
|
||||||
|
end;
|
||||||
type_size_check(Type, Bin) ->
|
type_size_check(Type, Bin) ->
|
||||||
case byte_size_for_type(Type) of
|
case byte_size_for_type(Type) of
|
||||||
not_applicable -> ok;
|
not_applicable -> ok;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
-module(gmser_chain_objects).
|
-module(gmser_chain_objects).
|
||||||
-vsn("0.1.2").
|
-vsn("0.2.0").
|
||||||
|
|
||||||
-export([ serialize/4
|
-export([ serialize/4
|
||||||
, deserialize/4
|
, deserialize/4
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(gmser_contract_code).
|
-module(gmser_contract_code).
|
||||||
-vsn("0.1.2").
|
-vsn("0.2.0").
|
||||||
|
|
||||||
-include("gmser_contract_code.hrl").
|
-include("gmser_contract_code.hrl").
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
%%% @end
|
%%% @end
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(gmser_delegation).
|
-module(gmser_delegation).
|
||||||
-vsn("0.1.2").
|
-vsn("0.2.0").
|
||||||
|
|
||||||
-export([ aens_preclaim_sig/3
|
-export([ aens_preclaim_sig/3
|
||||||
, aens_name_sig/4
|
, aens_name_sig/4
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
-module(gmser_dyn).
|
-module(gmser_dyn).
|
||||||
|
-vsn("0.2.0").
|
||||||
|
|
||||||
-export([ encode/1 %% (Term) -> rlp()
|
-export([ encode/1 %% (Term) -> rlp()
|
||||||
, encode/2 %% (Term, Types) -> rlp()
|
, encode/2 %% (Term, Types) -> rlp()
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
-module(gmser_dyn_types).
|
-module(gmser_dyn_types).
|
||||||
|
-vsn("0.2.0").
|
||||||
|
|
||||||
-export([ add_type/3 %% (Tag, Code, Template) -> Types1
|
-export([ add_type/3 %% (Tag, Code, Template) -> Types1
|
||||||
, add_type/4 %% (Tag, Code, Template, Types) -> Types1
|
, add_type/4 %% (Tag, Code, Template, Types) -> Types1
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
-module(gmser_id).
|
-module(gmser_id).
|
||||||
-vsn("0.1.2").
|
-vsn("0.2.0").
|
||||||
|
|
||||||
-export([ create/2
|
-export([ create/2
|
||||||
, specialize/1
|
, specialize/1
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
-module(gmser_rlp).
|
-module(gmser_rlp).
|
||||||
-vsn("0.1.2").
|
-vsn("0.2.0").
|
||||||
|
|
||||||
-export([ decode/1
|
-export([ decode/1
|
||||||
, decode_one/1
|
, decode_one/1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{application, gmserialization,
|
{application, gmserialization,
|
||||||
[{description, "Serialization of data for the Gajumaru"},
|
[{description, "Serialization of data for the Gajumaru"},
|
||||||
{vsn, "0.1.0"},
|
{vsn, "zomp"},
|
||||||
{registered, []},
|
{registered, []},
|
||||||
{applications,
|
{applications,
|
||||||
[kernel,
|
[kernel,
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
%% -*- erlang-mode; erlang-indent-level: 4; indent-tabs-mode: nil -*-
|
||||||
|
|
||||||
|
[{application, Name, Opts}] = CONFIG.
|
||||||
|
case lists:keyfind(vsn, 1, Opts) of
|
||||||
|
{vsn, "zomp"} ->
|
||||||
|
ZompMetaF = filename:join(filename:dirname(filename:dirname(SCRIPT)), "zomp.meta"),
|
||||||
|
{ok, ZMeta} = file:consult(ZompMetaF),
|
||||||
|
{_, {_, _, {Vmaj,Vmin,Vpatch}}} = lists:keyfind(package_id, 1, ZMeta),
|
||||||
|
VsnStr = unicode:characters_to_list(io_lib:fwrite("~w.~w.~w", [Vmaj, Vmin, Vpatch])),
|
||||||
|
Opts1 = lists:keyreplace(vsn, 1, Opts, {vsn, VsnStr}),
|
||||||
|
[{application, Name, Opts1}];
|
||||||
|
_ ->
|
||||||
|
CONFIG
|
||||||
|
end.
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
-module(gmserialization).
|
-module(gmserialization).
|
||||||
-vsn("0.1.2").
|
-vsn("0.2.0").
|
||||||
|
|
||||||
-export([ decode_fields/2
|
-export([ decode_fields/2
|
||||||
, decode_field/2
|
, decode_field/2
|
||||||
|
|||||||
@@ -22,10 +22,39 @@
|
|||||||
, {native_token , 32}
|
, {native_token , 32}
|
||||||
, {commitment , 32}
|
, {commitment , 32}
|
||||||
, {peer_pubkey , 32}
|
, {peer_pubkey , 32}
|
||||||
|
, {hash , 32}
|
||||||
, {state , 32}
|
, {state , 32}
|
||||||
, {poi , not_applicable}]).
|
, {poi , not_applicable}]).
|
||||||
|
|
||||||
encode_decode_test_() ->
|
encode_decode_test_() ->
|
||||||
|
encode_decode_test_(?TYPES).
|
||||||
|
|
||||||
|
encode_decode_known_types_test_() ->
|
||||||
|
KnownTypes = known_types(),
|
||||||
|
SizedTypes = [{T, ?TEST_MODULE:byte_size_for_type(T)} || T <- KnownTypes],
|
||||||
|
encode_decode_test_(SizedTypes).
|
||||||
|
|
||||||
|
prefixes_are_known_types_test() ->
|
||||||
|
MappedPfxs = mapped_prefixes(),
|
||||||
|
KnownTypes = known_types(),
|
||||||
|
lists:foreach(
|
||||||
|
fun({Pfx, Type}) ->
|
||||||
|
case lists:member(Type, KnownTypes) of
|
||||||
|
true -> ok;
|
||||||
|
false ->
|
||||||
|
error({not_a_known_type, Pfx, Type})
|
||||||
|
end
|
||||||
|
end, MappedPfxs),
|
||||||
|
lists:foreach(
|
||||||
|
fun(Type) ->
|
||||||
|
case lists:keyfind(Type, 2, MappedPfxs) of
|
||||||
|
{_, _} -> ok;
|
||||||
|
false ->
|
||||||
|
error({has_no_mapped_prefix, Type})
|
||||||
|
end
|
||||||
|
end, KnownTypes).
|
||||||
|
|
||||||
|
encode_decode_test_(Types) ->
|
||||||
[{"Byte sizes are correct",
|
[{"Byte sizes are correct",
|
||||||
fun() ->
|
fun() ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
@@ -33,7 +62,7 @@ encode_decode_test_() ->
|
|||||||
{_Type, _, ByteSize} = {Type, ByteSize,
|
{_Type, _, ByteSize} = {Type, ByteSize,
|
||||||
?TEST_MODULE:byte_size_for_type(Type)}
|
?TEST_MODULE:byte_size_for_type(Type)}
|
||||||
end,
|
end,
|
||||||
?TYPES)
|
Types)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
{"Serialize/deserialize known types",
|
{"Serialize/deserialize known types",
|
||||||
@@ -50,7 +79,7 @@ encode_decode_test_() ->
|
|||||||
{Type, Key} = ?TEST_MODULE:decode(EncodedKey),
|
{Type, Key} = ?TEST_MODULE:decode(EncodedKey),
|
||||||
{ok, Key} = ?TEST_MODULE:safe_decode(Type, EncodedKey)
|
{ok, Key} = ?TEST_MODULE:safe_decode(Type, EncodedKey)
|
||||||
end,
|
end,
|
||||||
?TYPES)
|
Types)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
{"Key size check works",
|
{"Key size check works",
|
||||||
@@ -58,17 +87,18 @@ encode_decode_test_() ->
|
|||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({_Type, not_applicable}) -> ok;
|
fun({_Type, not_applicable}) -> ok;
|
||||||
({Type, ByteSize}) ->
|
({Type, ByteSize}) ->
|
||||||
CheckIlligalSize =
|
CheckIllegalSize =
|
||||||
fun(S) ->
|
fun(S) ->
|
||||||
Key = <<42:S/unit:8>>,
|
Key = <<42:S/unit:8>>,
|
||||||
EncodedKey = ?TEST_MODULE:encode(Type, Key),
|
?assertError(incorrect_size, ?TEST_MODULE:encode(Type, Key)),
|
||||||
|
EncodedKey = ?TEST_MODULE:unsafe_encode(Type, Key), %% no size check
|
||||||
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, EncodedKey)
|
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, EncodedKey)
|
||||||
end,
|
end,
|
||||||
CheckIlligalSize(0),
|
CheckIllegalSize(0),
|
||||||
CheckIlligalSize(ByteSize - 1),
|
CheckIllegalSize(ByteSize - 1),
|
||||||
CheckIlligalSize(ByteSize + 1)
|
CheckIllegalSize(ByteSize + 1)
|
||||||
end,
|
end,
|
||||||
?TYPES)
|
Types)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
{"Missing prefix",
|
{"Missing prefix",
|
||||||
@@ -91,7 +121,7 @@ encode_decode_test_() ->
|
|||||||
<<_WholePrefix:3/unit:8, RestOfKey2/binary>> = EncodedKey,
|
<<_WholePrefix:3/unit:8, RestOfKey2/binary>> = EncodedKey,
|
||||||
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, RestOfKey2)
|
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, RestOfKey2)
|
||||||
end,
|
end,
|
||||||
?TYPES)
|
Types)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
{"Piece of encoded key",
|
{"Piece of encoded key",
|
||||||
@@ -110,7 +140,7 @@ encode_decode_test_() ->
|
|||||||
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, HalfKey),
|
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, HalfKey),
|
||||||
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, RestOfKey)
|
{error, invalid_encoding} = ?TEST_MODULE:safe_decode(Type, RestOfKey)
|
||||||
end,
|
end,
|
||||||
?TYPES)
|
Types)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
{"Encode/decode binary with only zeros",
|
{"Encode/decode binary with only zeros",
|
||||||
@@ -131,8 +161,58 @@ encode_decode_test_() ->
|
|||||||
Encoded1 = base58:binary_to_base58(Bin),
|
Encoded1 = base58:binary_to_base58(Bin),
|
||||||
Decoded1 = base58:base58_to_binary(Encoded1),
|
Decoded1 = base58:base58_to_binary(Encoded1),
|
||||||
?assertEqual(Bin, Decoded1)
|
?assertEqual(Bin, Decoded1)
|
||||||
end, ?TYPES)
|
end, Types)
|
||||||
end,
|
end,
|
||||||
Bins)
|
Bins)
|
||||||
end}
|
end},
|
||||||
|
{"Encode/decode keypairs",
|
||||||
|
fun() ->
|
||||||
|
KP1 = enacl:sign_keypair(),
|
||||||
|
Enc1 = ?TEST_MODULE:encode_keypair(KP1),
|
||||||
|
{ok, KP1} = ?TEST_MODULE:safe_decode_keypair(Enc1),
|
||||||
|
KP2 = enacl:sign_keypair(),
|
||||||
|
Enc2 = ?TEST_MODULE:encode_keypair(KP2),
|
||||||
|
{ok, KP2} = ?TEST_MODULE:safe_decode_keypair(Enc2),
|
||||||
|
BadEnc = Enc1#{~"priv" => maps:get(~"priv", Enc2)},
|
||||||
|
{error, illegal_encoding} = ?TEST_MODULE:safe_decode_keypair(BadEnc)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
{"Encode AND decode both 32-byte and 64-byte account_seckey",
|
||||||
|
fun() ->
|
||||||
|
%% Originally, we could encode a 64-byte seckey, but decode would fail.
|
||||||
|
#{public := Pub, secret := Sec} = enacl:sign_keypair(),
|
||||||
|
<<Seed:32/binary, Pub:32/binary>> = Sec,
|
||||||
|
EncSeed = ?TEST_MODULE:encode(account_seckey, Seed),
|
||||||
|
EncSec = ?TEST_MODULE:encode(account_seckey, Sec),
|
||||||
|
{ok, Seed} = ?TEST_MODULE:safe_decode(account_seckey, EncSeed),
|
||||||
|
{ok, Sec} = ?TEST_MODULE:safe_decode(account_seckey, EncSec)
|
||||||
|
end
|
||||||
|
}
|
||||||
].
|
].
|
||||||
|
|
||||||
|
known_types() ->
|
||||||
|
Forms = get_forms(),
|
||||||
|
[{type, _, union, Types}] =
|
||||||
|
[Def || {attribute, _, type, {known_type, Def, []}} <- Forms],
|
||||||
|
[Name || {atom,_, Name} <- Types].
|
||||||
|
|
||||||
|
mapped_prefixes() ->
|
||||||
|
Forms = get_forms(),
|
||||||
|
[Clauses] = [Cs || {function,_,pfx2type,1,Cs} <- Forms],
|
||||||
|
Abst = [{B, A} || {clause,_,[B],[],[A]} <- Clauses],
|
||||||
|
lists:map(
|
||||||
|
fun({B, A}) ->
|
||||||
|
{eval_expr(B), eval_expr(A)}
|
||||||
|
end, Abst).
|
||||||
|
|
||||||
|
get_forms() ->
|
||||||
|
get_forms(code:which(?TEST_MODULE)).
|
||||||
|
|
||||||
|
get_forms(Beam) ->
|
||||||
|
{ok, {_, [{abstract_code, {raw_abstract_v1, Forms}}]}} =
|
||||||
|
beam_lib:chunks(Beam, [abstract_code]),
|
||||||
|
Forms.
|
||||||
|
|
||||||
|
eval_expr(Expr) ->
|
||||||
|
{value, Val, []} = erl_eval:expr(Expr, []),
|
||||||
|
Val.
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
{type,lib}.
|
{type,lib}.
|
||||||
{modules,[]}.
|
{modules,[]}.
|
||||||
{prefix,none}.
|
{prefix,none}.
|
||||||
{author,"Hans Svensson"}.
|
|
||||||
{desc,"Serialization helpers for the Gajumaru."}.
|
{desc,"Serialization helpers for the Gajumaru."}.
|
||||||
{package_id,{"otpr","gmserialization",{0,1,2}}}.
|
{author,"Hans Svensson"}.
|
||||||
|
{package_id,{"otpr","gmserialization",{0,2,0}}}.
|
||||||
{deps,[{"otpr","eblake2",{1,0,1}},{"otpr","base58",{0,1,1}}]}.
|
{deps,[{"otpr","eblake2",{1,0,1}},{"otpr","base58",{0,1,1}}]}.
|
||||||
{key_name,none}.
|
{key_name,none}.
|
||||||
{a_email,[]}.
|
{a_email,[]}.
|
||||||
|
|||||||
Executable
+49
@@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
APP=$(basename "$PWD")
|
||||||
|
|
||||||
|
SRC="_build/default/lib/$APP"
|
||||||
|
DST="$PWD/_build/zomp/lib/$APP"
|
||||||
|
IGNORE_FILE="zomp.ignore"
|
||||||
|
|
||||||
|
mkdir -p "$DST"
|
||||||
|
|
||||||
|
# Remove broken symlinks
|
||||||
|
find "$SRC" -type l ! -exec test -e {} \; -delete || true
|
||||||
|
|
||||||
|
# Build ignore matcher
|
||||||
|
IGNORE_TEMP=$(mktemp)
|
||||||
|
trap "rm -f $IGNORE_TEMP" EXIT
|
||||||
|
|
||||||
|
# Expand globs in zomp.ignore to patterns suitable for grep
|
||||||
|
if [ -e "$IGNORE_FILE" ]; then
|
||||||
|
grep -v '^\s*#' "$IGNORE_FILE" | sed 's#/#\\/#g' | sed 's/\./\\./g' | sed 's/\*/.*/g' > "$IGNORE_TEMP"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy Git-tracked and Zomp-allowed files
|
||||||
|
git ls-files -z | while IFS= read -r -d '' file; do
|
||||||
|
# Skip if ignored
|
||||||
|
echo "$file" | grep -Eq -f "$IGNORE_TEMP" && continue
|
||||||
|
# Only copy if file exists in the build dir
|
||||||
|
if [ -e "$SRC/$file" ]; then
|
||||||
|
mkdir -p "$DST/$(dirname "$file")"
|
||||||
|
cp -a "$SRC/$file" "$DST/$file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
rm "$IGNORE_TEMP"
|
||||||
|
|
||||||
|
# Copy metadata
|
||||||
|
cp "$PWD/zomp.meta" "$DST/"
|
||||||
|
cp "$PWD/Emakefile" "$DST/"
|
||||||
|
|
||||||
|
# copy generated schema
|
||||||
|
SCHEMA="$SRC/priv/gmhc_schema.json"
|
||||||
|
if [ -e "$SCHEMA" ]; then
|
||||||
|
mkdir -p "$DST/priv"
|
||||||
|
cp -a "$SCHEMA" "$DST/priv/$(basename "$SCHEMA")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up beam files just in case
|
||||||
|
[ -d "$DST/ebin" ] && find "$DST/ebin" -name '*.beam' -exec rm -f {} + || true
|
||||||
Reference in New Issue
Block a user