From 6ef34e0564cd1fb01831a3bce2858b497bf90b4c Mon Sep 17 00:00:00 2001 From: Luca Succi Date: Fri, 11 Sep 2026 12:07:18 +0200 Subject: [PATCH 1/4] fix dialyzer --- src/grisp_tools.app.src | 5 ++++- src/grisp_tools.hrl | 4 +++- src/grisp_tools_configure.erl | 27 ++++++++++++++++----------- src/grisp_tools_firmware.erl | 7 +++++-- src/grisp_tools_io.erl | 19 +++++++++---------- src/grisp_tools_pack.erl | 7 +++++-- src/grisp_tools_report.erl | 4 ++-- src/grisp_tools_util.erl | 3 +-- 8 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/grisp_tools.app.src b/src/grisp_tools.app.src index f0ad5c6..3e6a70f 100644 --- a/src/grisp_tools.app.src +++ b/src/grisp_tools.app.src @@ -7,9 +7,12 @@ stdlib, ssl, inets, + xmerl, bbmustache, mapz, - hackney + hackney, + edifa, + grisp_update_packager ]}, {env, [ {cdn, "https://s3.amazonaws.com/grisp"}, diff --git a/src/grisp_tools.hrl b/src/grisp_tools.hrl index f7f6221..b3c15d6 100644 --- a/src/grisp_tools.hrl +++ b/src/grisp_tools.hrl @@ -14,8 +14,10 @@ #{role => system, type => fat32, size => ?GRISP2_SYSTEM_SIZE, start => ?GRISP2_RESERVED_SIZE}, #{role => system, type => fat32, size => ?GRISP2_SYSTEM_SIZE} ]). +-define(GRISP2_EDIFA_PARTITIONS, + [maps:without([role], Partition) || Partition <- ?GRISP2_PARTITIONS]). -define(GRISP2_FAT_TYPE, 32). -define(GRISP2_FAT_CLUSTER_SIZE, 4). --endif. % GRISP_TOOLS_HRL \ No newline at end of file +-endif. % GRISP_TOOLS_HRL diff --git a/src/grisp_tools_configure.erl b/src/grisp_tools_configure.erl index 6614f3b..41179c8 100644 --- a/src/grisp_tools_configure.erl +++ b/src/grisp_tools_configure.erl @@ -11,7 +11,7 @@ type :: setting_type(), default = none :: none | string() | boolean(), description :: string(), - dep_setting_fun :: function(), + dep_setting_fun = undefined :: function() | undefined, hint = "" :: string()}). %--- Types --------------------------------------------------------------------- @@ -20,7 +20,6 @@ % @doc {Long, Short, Type, Default, Descr} -type setting() :: {atom(), char() | undefined, - string(), {setting_type(), string() | boolean()}, string()}. @@ -86,7 +85,7 @@ user_provided_event(State, Key, UserOpts) -> -spec validate_user_choice(State, Setting) -> {ok, State} | {error, Error} when State :: map(), Setting :: atom(), - Error :: atom(). + Error :: string(). validate_user_choice(State, name) -> {ok, Cwd} = file:get_cwd(), #{flags := #{name := ProjectName, interactive := Interactive}} = State, @@ -191,7 +190,7 @@ epmd_options() -> [ default = "grisp", description = "The distributed Erlang cookie", hint = "Cookie is necessary for remote shell."}]. --spec format_settings_options([set_opts()], [setting()]) -> setting(). +-spec format_settings_options([set_opts()], [setting()]) -> [setting()]. format_settings_options([], Acc) -> Acc; format_settings_options([#set_opts{dep_setting_fun = undefined} = O |T], Acc) -> @@ -213,21 +212,19 @@ format_settings_options([SetOpts | Tail], Acc) -> default_author_and_email() -> %% See if we can get a git user and email to use as defaults - case rebar_utils:sh("git config --global user.name", [return_on_error]) of + case command("git config --global user.name") of {ok, Name} -> - case rebar_utils:sh("git config --global user.email", - [return_on_error]) of + case command("git config --global user.email") of {ok, Email} -> - {rebar_string:trim(Name, both, "\n"), - rebar_string:trim(Email, both, "\n")}; + {string:trim(Name, both, "\n"), + string:trim(Email, both, "\n")}; {error, _} -> %% Use neither if one doesn't exist {"Anonymous", "anonymous@example.org"} end; {error, _} -> %% Ok, try mecurial - case rebar_utils:sh("hg showconfig ui.username", - [return_on_error]) of + case command("hg showconfig ui.username") of {ok, NameEmail} -> case re:run(NameEmail, "^(.*) <(.*)>$", [{capture, [1, 2], list}, unicode]) of @@ -240,3 +237,11 @@ default_author_and_email() -> {"Anonymous", "anonymous@example.org"} end end. + +command(Command) -> + try os:cmd(Command, #{exception_on_failure => true}) of + Output -> {ok, Output} + catch + error:{command_failed, _Output, _ExitStatus} -> + {error, command_failed} + end. diff --git a/src/grisp_tools_firmware.erl b/src/grisp_tools_firmware.erl index 5e08753..5dace0c 100644 --- a/src/grisp_tools_firmware.erl +++ b/src/grisp_tools_firmware.erl @@ -172,7 +172,7 @@ copy_bootloader(State = #{edifa_pid := Pid, bootloader := BootFile}) -> create_partitions(State = #{edifa_pid := Pid}) -> Opts = edifa_opts(State), - case edifa:partition(Pid, mbr, ?GRISP2_PARTITIONS, Opts) of + case edifa:partition(Pid, mbr, ?GRISP2_EDIFA_PARTITIONS, Opts) of {ok, [_, _] = Partitions, State2} -> State2#{partitions => Partitions}; {error, Reason, State2} -> @@ -265,7 +265,10 @@ if_key_defined(State, Key, Result, Default) -> end. edifa_opts(State) -> - edifa_opts(State, #{}). + #{ + log_handler => fun edifa_log_hanler/2, + log_state => State + }. edifa_opts(State, Opts) -> Opts#{ diff --git a/src/grisp_tools_io.erl b/src/grisp_tools_io.erl index 484781e..ff07c7e 100644 --- a/src/grisp_tools_io.erl +++ b/src/grisp_tools_io.erl @@ -102,8 +102,7 @@ get(trim_string, []) -> get(trim_string, String) -> case is_list(String) of true -> - Whitespace = unicode_util:whitespace(), - Trimmed = string:trim(String, both, Whitespace ++ [$"]), + Trimmed = string:trim(String, both, unicode_whitespace() ++ [$"]), unicode:characters_to_binary(Trimmed); false -> no_clue @@ -118,14 +117,14 @@ get(string, String) -> no_clue end. --ifdef(unicode_str). -trim(Str, right, Chars) -> string:trim(Str, trailing, Chars); -trim(Str, left, Chars) -> string:trim(Str, leading, Chars); -trim(Str, both, Chars) -> string:trim(Str, both, Chars). --else. -trim(Str) -> string:strip(rebar_utils:to_list(Str)). -trim(Str, Dir, [Chars|_]) -> string:strip(rebar_utils:to_list(Str), Dir, Chars). --endif. +trim(Str) -> string:trim(unicode:characters_to_list(Str)). +trim(Str, both, Chars) -> string:trim(unicode:characters_to_list(Str), both, Chars). + +unicode_whitespace() -> + [$\t, $\n, $\v, $\f, $\r, $\s, 16#85, 16#A0, 16#1680, + 16#2000, 16#2001, 16#2002, 16#2003, 16#2004, 16#2005, 16#2006, + 16#2007, 16#2008, 16#2009, 16#200A, 16#2028, 16#2029, 16#202F, + 16#205F, 16#3000]. say(State, Say) -> Event = {say, Say}, diff --git a/src/grisp_tools_pack.erl b/src/grisp_tools_pack.erl index a9c350c..4ba67a4 100644 --- a/src/grisp_tools_pack.erl +++ b/src/grisp_tools_pack.erl @@ -124,7 +124,7 @@ create_image(State = #{temp_dir := TempDir}) -> create_partitions(State = #{edifa_pid := Pid}) -> Opts = edifa_opts(State), - case edifa:partition(Pid, mbr, ?GRISP2_PARTITIONS, Opts) of + case edifa:partition(Pid, mbr, ?GRISP2_EDIFA_PARTITIONS, Opts) of {ok, [_, _] = Partitions, State2} -> State2#{partitions => Partitions}; {error, Reason, State2} -> @@ -204,7 +204,10 @@ cleanup_image(State) -> %--- Internal ------------------------------------------------------------------ edifa_opts(State) -> - edifa_opts(State, #{}). + #{ + log_handler => fun edifa_log_hanler/2, + log_state => State + }. edifa_opts(State, Opts) -> Opts#{ diff --git a/src/grisp_tools_report.erl b/src/grisp_tools_report.erl index c4747dc..483bf8d 100644 --- a/src/grisp_tools_report.erl +++ b/src/grisp_tools_report.erl @@ -7,7 +7,7 @@ -import(grisp_tools_util, [shell/2]). -import(grisp_tools_util, [shell/3]). -import(grisp_tools_util, [ensure_dir/1]). --import(grisp_tools_util, [write_file/3]). +-import(grisp_tools_util, [copy_file/3]). %--- API ----------------------------------------------------------------------- @@ -100,7 +100,7 @@ copy_project_file(Filename, #{project_root := Root, Dst = filename:join(ReportDir, Filename), Copy = #{source => Src, target => Dst}, try - write_file(Root, Copy, #{}), + copy_file(Root, Copy, #{}), event(S0, [files, {copy, Dst}]) catch error:_ -> event(S0, [files, {missing, Src}]) diff --git a/src/grisp_tools_util.erl b/src/grisp_tools_util.erl index 7ebb3cf..56c0e79 100644 --- a/src/grisp_tools_util.erl +++ b/src/grisp_tools_util.erl @@ -221,8 +221,7 @@ select_overlay_folders(_, [], Selected) -> lists:sort(Selected); select_overlay_folders({V, _Pre, _Build, Full} = Version, [D|Dirs], Selected) -> FN = otp_version_components(D), - FullName = unicode:characters_to_list(Full), - case D =:= FullName orelse is_elegible_version(FN, V) of + case D =:= Full orelse is_elegible_version(FN, V) of true -> select_overlay_folders(Version, Dirs, [D | Selected]); false -> select_overlay_folders(Version, Dirs, Selected) end. From 09c1f0a69e01fc2c82024528340082f7a44a5d73 Mon Sep 17 00:00:00 2001 From: Luca Succi Date: Fri, 11 Sep 2026 12:08:03 +0200 Subject: [PATCH 2/4] Run dialyzer in CI --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a66db00..0170692 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,3 +36,6 @@ jobs: - name: Compile run: rebar3 do clean, compile + + - name: Dialyzer + run: rebar3 dialyzer From d4fdb1b44cb0a7d4cf9f2164eaa64998eea129b0 Mon Sep 17 00:00:00 2001 From: Luca Succi Date: Fri, 11 Sep 2026 12:15:47 +0200 Subject: [PATCH 3/4] Remove unused source_hash fun --- src/grisp_tools_util.erl | 71 ---------------------------------------- 1 file changed, 71 deletions(-) diff --git a/src/grisp_tools_util.erl b/src/grisp_tools_util.erl index 56c0e79..73efd0e 100644 --- a/src/grisp_tools_util.erl +++ b/src/grisp_tools_util.erl @@ -27,7 +27,6 @@ -export([build_hash/1]). -export([build_hash_format/1]). -export([merge_build_config/2]). --export([source_hash/2]). -export([copy_directory/4, copy_directory/5]). -export([copy_file/3, copy_file/4]). -export([write_file/3, write_file/4]). @@ -271,18 +270,6 @@ build_hash(#{build := #{overlay := Overlay}}) -> build_hash_format(Index) -> [io_lib:format("~s ~s~n", [File, Hash]) || {File, Hash} <- Index]. -source_files(Apps, Board) -> - lists:foldl(fun({_App, #{dir := Dir}}, {Sys, Drivers, NIFs}) -> - {AppSys, AppDrivers, AppNIFs} = collect_c_sources(Dir, Board), - {maps:merge(Sys, AppSys), maps:merge(Drivers, AppDrivers), maps:merge(NIFs, AppNIFs)} - end, {#{}, #{}, #{}}, Apps). - -source_hash(Apps, Board) -> - {DriverFiles, SystemFiles, NIFFiles} = source_files(Apps, Board), - Targets = maps:merge(DriverFiles, SystemFiles), - Targets2 = maps:merge(Targets, NIFFiles), - hash_files(Targets2). - copy_directory(State0, Src, DestRoot, DestRel) -> recursive_copy(State0, Src, DestRoot, DestRel, [], #{}). @@ -468,64 +455,6 @@ sub_paths(Dir, Platform) -> cache() -> filename:basedir(user_cache, "grisp"). -collect_c_sources(Dir, Board) -> - Source = filename:join([Dir, "grisp", Board]), - case filelib:is_dir(Source) of - true -> {collect_sys(Source), collect_drivers(Source), collect_nifs(Source)}; - false -> {#{}, #{}, #{}} - end. - -collect_sys(Source) -> - maps:merge( - collect_files({Source, "sys/*.h"}, "erts/emulator/sys/unix"), - collect_files({Source, "sys/*.c"}, "erts/emulator/sys/unix") - ). - -collect_drivers(Source) -> - maps:merge( - collect_files( - {Source, "drivers/*.h"}, - "erts/emulator/drivers/unix" - ), - collect_files( - {Source, "drivers/*.c"}, - "erts/emulator/drivers/unix" - ) - ). - -collect_nifs(Source) -> - maps:merge( - collect_files( - {Source, "nifs/*.h"}, - "erts/emulator/nifs/common" - ), - collect_files( - {Source, "nifs/*.c"}, - "erts/emulator/nifs/common" - ) - ). - -collect_files({SourceRoot, Pattern}, Target) -> - Files = filelib:wildcard(filename:join(SourceRoot, Pattern)), - lists:foldl(fun(File, Collected) -> - TargetFile = filename:join([Target, filename:basename(File)]), - Collected#{TargetFile => File} - end, #{}, Files). - -hash_files(Targets) -> - Sorted = lists:keysort(1, maps:to_list(Targets)), - FileHashes = lists:map(fun({Target, Source}) -> - {ok, Hash} = hash_file(Source, sha256), - {Target, Hash} - end, Sorted), - - HashIndex = lists:map(fun({Target, Hash}) -> - io_lib:format("~s ~s~n", [Target, format_hash(sha256, Hash)]) end, - FileHashes), - - TopHash = format_hash(sha256, crypto:hash(sha256, HashIndex)), - {TopHash, HashIndex}. - hash_file(File, Algorithm) -> Context = crypto:hash_init(Algorithm), with_file(File, [binary, raw, read], fun(Handle) -> From 660f04c6e0555c6675021ef27544dd6c7157655b Mon Sep 17 00:00:00 2001 From: Luca Succi Date: Fri, 11 Sep 2026 12:25:53 +0200 Subject: [PATCH 4/4] Do not test OTP 27 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0170692..5cedb4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: name: Erlang ${{matrix.otp}} / rebar ${{matrix.rebar3}} strategy: matrix: - otp: ['27', '28', '29'] + otp: ['28', '29'] rebar3: ['3'] steps: