Skip to content

Commit

Permalink
Add more tests (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
paulo-ferraz-oliveira authored Aug 14, 2023
1 parent 77b5332 commit 9a801ef
Show file tree
Hide file tree
Showing 15 changed files with 243 additions and 116 deletions.
1 change: 1 addition & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
erlang 25.3.2.5
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,14 @@ There are no compulsory options (all defaults are those assumed by `shellcheck`)
% Output format (checkstyle, diff, gcc, json, json1, quiet, tty)
{format, checkstyle | diff | gcc | json | json1 | quiet | tty},

% List checks disabled by default
list_optional,

% Don't look for .shellcheckrc files
norc,

% List of optional checks to enable (or 'all')
{enable, ["check1", "check2"] | all},

% Specify path when looking for sourced files ("SCRIPTDIR" for script's dir)
{source_paths, "SOURCEPATHS"},
{source_path, "SOURCEPATH"},

% Specify dialect (sh, bash, dash, ksh)
{shell, sh | bash | dash | ksh},
Expand Down Expand Up @@ -88,16 +85,19 @@ and apply the analysis on top of that.

### Check it out

<!-- markdownlint-disable MD013 -->
```console
===> Compiling rebar3_checkshell
In script.sh line 2:
VAR=none
^-- SC2034: VAR appears unused. Verify use (or export if used externally).
===> checkshell: analysis starting. This may take a while...
In sh/fish.sh line 1:
#!/usr/bin/env fish
^-- SC1008 (error): This shebang was unrecognized. ShellCheck only supports sh/bash/dash/ksh. Add a 'shell' directive to specify.

For more information:
https://www.shellcheck.net/wiki/SC2034 -- A appears unused. Verify use (or ...
https://www.shellcheck.net/wiki/SC1008 -- This shebang was unrecognized. Sh...
===> checkshell: ShellCheck exited with error
```
<!-- markdownlint-enable -->

### Ignoring issues

Expand Down
7 changes: 7 additions & 0 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Example

Check `rebar.config` (only one thing required).

Run it with `rebar3 checkshell --files=sh/for.sh`.

Expect an error!
1 change: 1 addition & 0 deletions example/_checkouts/rebar3_checkshell
1 change: 1 addition & 0 deletions example/rebar.config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{project_plugins, [rebar3_checkshell]}.
1 change: 1 addition & 0 deletions example/sh/empty.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/bash
2 changes: 2 additions & 0 deletions example/sh/fish.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env fish

3 changes: 3 additions & 0 deletions example/sh/for.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

for f in *; do echo "$f" done
3 changes: 2 additions & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,13 @@
{profiles, [
{test, [
{cover_enabled, true},
{cover_excl_mods, [rebar3_checkshell]},
{cover_opts, [verbose]},
{deps, [{meck, "0.9.2"}]},
{erl_opts, [
debug_info,
report,
verbose,
nowarn_export_all,
nowarn_missing_spec_all,
warnings_as_errors
]},
Expand Down
100 changes: 18 additions & 82 deletions src/rebar3_checkshell_arch.erl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

-export_type([nonempty_ubytes/0]).

-elvis([{elvis_style, no_debug_call, disable}]).

-spec do(Files, State) -> Result when
Files :: [string()],
Result :: {ok, State} | {error, nonempty_ubytes()}.
Expand Down Expand Up @@ -84,104 +86,38 @@ maybe_colorize(_Color) ->
Result :: string() | list().
opt(check_sourced) ->
"--check-sourced";
opt({color, Color}) when Color =:= auto orelse Color =:= always orelse Color =:= never ->
opt({color, Color}) ->
"--color=" ++ atom_to_list(Color);
opt({include, Includes}) ->
"--include=" ++
lists:foldl(
fun
(Include, "" = _Acc) when is_list(Include) ->
Include;
(Include, Acc) when is_list(Include) ->
Acc ++ "," ++ Include;
(Include, Acc) ->
_ = rebar_log:log(
warn,
"checkshell: non-string value for option include: ~p",
[Include]
),
Acc
end,
"",
Includes
);
"--include=" ++ string:join(Includes, ",");
opt({exclude, Excludes}) ->
"--exclude=" ++
lists:foldl(
fun
(Exclude, "" = _Acc) when is_list(Exclude) ->
Exclude;
(Exclude, Acc) when is_list(Exclude) ->
Acc ++ "," ++ Exclude;
(Exclude, Acc) ->
_ = rebar_log:log(
warn,
"checkshell: non-string value for option exclude: ~p",
[Exclude]
),
Acc
end,
"",
Excludes
);
opt({format, Format}) when
Format =:= checkstyle orelse
Format =:= diff orelse
Format =:= gcc orelse
Format =:= json orelse
Format =:= json1 orelse
Format =:= quiet orelse
Format =:= tty
->
"--exclude=" ++ string:join(Excludes, ",");
opt({format, Format}) ->
"--format=" ++ atom_to_list(Format);
opt(list_optional) ->
"--list-optional";
opt(norc) ->
"--norc";
opt({enable, Checks}) when is_list(Checks) ->
"--enable=" ++
lists:foldl(
fun
(Check, "" = _Acc) when is_list(Check) ->
Check;
(Check, Acc) when is_list(Check) ->
Acc ++ "," ++ Check;
(Check, Acc) ->
_ = rebar_log:log(
warn,
"checkshell: non-string value for option enable: ~p",
[Check]
),
Acc
end,
"",
Checks
);
opt({enable, all}) ->
"--enable=all";
opt({source_paths, SourcePaths}) when is_list(SourcePaths) ->
"--source-path=" ++ SourcePaths;
opt({shell, Shell}) when
Shell =:= sh orelse Shell =:= bash orelse Shell =:= dash orelse Shell =:= ksh
->
opt({enable, Checks}) ->
"--enable=" ++ string:join(Checks, ",");
opt({source_path, SourcePath}) ->
"--source-path=" ++ SourcePath;
opt({shell, Shell}) ->
"--shell=" ++ atom_to_list(Shell);
opt({severity, Severity}) when
Severity =:= error orelse
Severity =:= warning orelse
Severity =:= info orelse
Severity =:= style
->
opt({severity, Severity}) ->
"--severity=" ++ atom_to_list(Severity);
opt({wiki_link_count, Num}) when is_integer(Num) andalso Num > 0 ->
opt({wiki_link_count, Num}) ->
"--wiki-link-count=" ++ integer_to_list(Num);
opt(external_sources) ->
"--external-sources";
opt({files, Files}) when is_list(Files) ->
opt({files, Files}) ->
Files;
opt(UnknownOption) ->
_ = rebar_log:log(
_ = rebar3_checkshell_utils:log(
warn,
"checkshell: unknown rebar.config option ~p",
"unknown rebar.config option ~p",
[UnknownOption]
),
"".
Expand All @@ -191,6 +127,6 @@ opt(UnknownOption) ->
AnalysisRes :: string(),
Result :: ok.
output_shellcheck_analysis(1 = _Failure, AnalysisRes) when length(AnalysisRes) > 1 ->
_ = rebar_log:log(warn, "~p", [string:sub_string(AnalysisRes, 2)]);
io:format("~s", [string:sub_string(AnalysisRes, 2)]);
output_shellcheck_analysis(_Failure, AnalysisRes) ->
_ = rebar_log:log(warn, "~p", [AnalysisRes]).
rebar3_checkshell_utils:log(warn, "~p", [AnalysisRes], false).
46 changes: 30 additions & 16 deletions src/rebar3_checkshell_inst.erl
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,16 @@ executable_for(win32) ->
Exists :: boolean(),
Result :: ok | {error, file:posix()}.
mkdir_arch_cache(true = _Exists) ->
_ = rebar_log:log(debug, "checkshell: arch. cache dir exists", []),
_ = rebar3_checkshell_utils:log(debug, "arch. cache dir exists", []),
ok;
mkdir_arch_cache(false = _Exists) ->
ArchFolderName = arch_folder_name(),
ArchCacheDir = arch_cache_dir(),
_ = rebar_log:log(info, "checkshell: creating cache/arch. dir (arch: ~p) at ~p", [
ArchFolderName, ArchCacheDir
]),
_ = rebar3_checkshell_utils:log(
info, "creating cache/arch. dir (arch: ~p) at ~p", [
ArchFolderName, ArchCacheDir
]
),
filelib:ensure_path(ArchCacheDir).

-spec mkdir_vsn_cache(Exists, CacheDirResult, State) -> Result when
Expand All @@ -138,14 +140,18 @@ mkdir_arch_cache(false = _Exists) ->
State :: rebar_state:t(),
Result :: ok | {error, file:posix()}.
mkdir_vsn_cache(true = _Exists, _CacheDirResult, _State) ->
_ = rebar_log:log(debug, "checkshell: vsn cache dir exists", []),
_ = rebar3_checkshell_utils:log(debug, "vsn cache dir exists", []),
ok;
mkdir_vsn_cache(false = _Exists, {error, _FilePosix} = CacheDirResult, _State) ->
_ = rebar_log:log(debug, "checkshell: (vsn cache) prior error ~p", [CacheDirResult]),
_ = rebar3_checkshell_utils:log(debug, "(vsn cache) prior error ~p", [
CacheDirResult
]),
CacheDirResult;
mkdir_vsn_cache(false = _Exists, ok = _CacheDirResult, State) ->
VsnCacheDir = vsn_cache_dir(State),
_ = rebar_log:log(info, "checkshell: creating cache/version dir at ~p", [VsnCacheDir]),
_ = rebar3_checkshell_utils:log(info, "creating cache/version dir at ~p", [
VsnCacheDir
]),
filelib:ensure_path(VsnCacheDir).

-spec download_url(State) -> Result when
Expand All @@ -162,18 +168,20 @@ download_url(State) ->
State :: rebar_state:t(),
Result :: ok | {error, file:posix()}.
download_and_write(true = _CompressedTargetExists, _VsnDirResult, _State) ->
_ = rebar_log:log(debug, "checkshell: compressed target exists", []),
_ = rebar3_checkshell_utils:log(debug, "compressed target exists", []),
ok;
download_and_write(false = _CompressedTargetExists, {error, _FilePosix} = VsnDirResult, _State) ->
_ = rebar_log:log(debug, "checkshell: (download and write) prior error ~p", [VsnDirResult]),
_ = rebar3_checkshell_utils:log(debug, "(download and write) prior error ~p", [
VsnDirResult
]),
VsnDirResult;
download_and_write(false = _CompressedTargetExists, ok = _VsnDirResult, State) ->
URL = download_url(State),
VsnCacheDir = vsn_cache_dir(State),
HttpHeaders = [],
HttpOptions = [{ssl, tls_certificate_check:options(URL)}],
Options = [{body_format, binary}],
_ = rebar_log:log(info, "checkshell: downloading ~p to ~p", [URL, VsnCacheDir]),
_ = rebar3_checkshell_utils:log(info, "downloading ~p to ~p", [URL, VsnCacheDir]),
{ok, {{_HttpVersion, 200, _Status}, _HttpHeaders, HttpBodyResult}} = httpc:request(
get, {URL, HttpHeaders}, HttpOptions, Options
),
Expand All @@ -194,10 +202,14 @@ should_checksum(State) ->
State :: rebar_state:t(),
Result :: ok | {error, nonempty_ubytes()}.
checksum(false = _CheckSummed, _ExpandResult, _State) ->
_ = rebar_log:log(warn, "checkshell: checksum bypass is ON", []),
_ = rebar3_checkshell_utils:log(warn, "checksum bypass is ON", []),
ok;
checksum(true = _CheckSummed, {error, FilePosix} = ExpandResult, _State) ->
_ = rebar_log:log(debug, "checkshell: (expand for) prior error ~p", [ExpandResult]),
_ = rebar3_checkshell_utils:log(
debug,
"(checksum) prior error ~p",
[ExpandResult]
),
{error, "(check with DEBUG=1) " ++ atom_to_list(FilePosix)};
checksum(true = _CheckSummed, ok = _ExpandResult, State) ->
{ok, ShellCheck} = file:read_file(shellcheck_path(State)),
Expand All @@ -212,7 +224,7 @@ do_checksum(Arch, Checksum) when
(Arch =:= linux andalso Checksum =:= ?LINUX_CHECKSUM) orelse
(Arch =:= win32 andalso Checksum =:= ?WIN32_CHECKSUM)
->
_ = rebar_log:log(debug, "checkshell: checksum is Ok for arch. ~p", [Arch]),
_ = rebar3_checkshell_utils:log(debug, "checksum is Ok for arch. ~p", [Arch]),
ok;
do_checksum(_Arch, _Expected) ->
{error, "invalid executable checksum"}.
Expand All @@ -231,16 +243,18 @@ expand(ExpandedExists, DownloadAndWriteResult, State) ->
State :: rebar_state:t(),
Result :: ok | {error, file:posix()}.
expand_for(true = _ExpandedExists, _DownloadAndWriteResult, _State) ->
_ = rebar_log:log(debug, "checkshell: expanded target exists", []),
_ = rebar3_checkshell_utils:log(debug, "expanded target exists", []),
ok;
expand_for(false = _ExpandedExists, {error, _Result} = DownloadAndWriteResult, _State) ->
_ = rebar_log:log(debug, "checkshell: (expand for) prior error ~p", [DownloadAndWriteResult]),
_ = rebar3_checkshell_utils:log(debug, "(expand for) prior error ~p", [
DownloadAndWriteResult
]),
DownloadAndWriteResult;
expand_for(false = _ExpandedExists, ok = _DownloadAndWriteResult, State) ->
FileType = file_type(),
CompressedTarget = compressed_target(State),
VsnCacheDir = vsn_cache_dir(State),
_ = rebar_log:log(info, "checkshell: extracting executable to ~p", [VsnCacheDir]),
_ = rebar3_checkshell_utils:log(info, "extracting executable to ~p", [VsnCacheDir]),
do_expand_for(FileType, CompressedTarget, VsnCacheDir).

-spec do_expand_for(FileType, CompressedTarget, TargetDir) -> Result when
Expand Down
6 changes: 3 additions & 3 deletions src/rebar3_checkshell_prv.erl
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ do(State) ->
Files :: [string()],
Result :: {ok, State} | {error, nonempty_ubytes()}.
do_for(Files, State) ->
_ = rebar_log:log(
info, "checkshell: analysis starting. This may take a while...", []
_ = rebar3_checkshell_utils:log(
info, "analysis starting. This may take a while...", []
),
rebar3_checkshell_arch:do(Files, State).

Expand Down Expand Up @@ -93,7 +93,7 @@ opt(State, Opt) ->
Default :: term(),
Result :: undefined | opt().
opt(State, Opt, Default) ->
Opts = opts(State),
Opts = ?MODULE:opts(State),
proplists:get_value(Opt, Opts, Default).

-spec files_from_cli(State) -> Result when
Expand Down
Loading

0 comments on commit 9a801ef

Please sign in to comment.