Skip to content

Instantly share code, notes, and snippets.

@ohnit
Last active January 9, 2024 16:27
Show Gist options
  • Save ohnit/15e752d61f3b960bcc496858b0dcc5f2 to your computer and use it in GitHub Desktop.
Save ohnit/15e752d61f3b960bcc496858b0dcc5f2 to your computer and use it in GitHub Desktop.
Diffs credo and dialyzer outputs with the output saved when it was run on the last commits
#! /bin/bash
# Diffs credo and dialyzer outputs with the output saved when it was run on the last commits
DIFF_TOOL="code --diff"
EDITOR="code"
check_dirty() {
if [ -n "$(git status --porcelain)" ]; then
echo true
else
echo false
fi;
}
get_previous_commit_id() {
local commit
if [[ $is_dirty = true ]] || [[ $to_dirty = true ]]; then
commit=$(git rev-parse HEAD)
else
commit=$(git rev-parse HEAD^)
fi;
if [[ $to_dirty = true ]]; then
echo "${commit}-dirty"
else
echo "$commit"
fi;
}
get_current_commit_id() {
local commit
commit=$(git rev-parse HEAD)
if [[ $is_dirty = true ]]; then
echo "${commit}-dirty"
else
echo "$commit"
fi;
}
keep_x_newest_files() {
local dir
dir="$1"
to_keep="$2"
# shellcheck disable=SC2010
(cd "$dir" && ls -tp | grep -v '/$' | tail -n +"$to_keep" | xargs -I {} rm -- {})
}
do_credo() {
local curr_file prev_file credo_dir
credo_dir="$check_dir/credo"
prev_file="$credo_dir/credo_$previous_commit_id.txt"
curr_file="$credo_dir/credo_$current_commit_id.txt"
if [[ -f "$prev_file" ]] && [[ $to_dirty == true ]]; then
old_prev="$prev_file"
new_prev="$credo_dir/credo_$previous_commit_id-old.txt"
cp "$old_prev" "$new_prev"
prev_file="$new_prev"
fi
printf "\nCredo:\n"
echo "previous_file: $prev_file"
echo "current_file: $curr_file"
if [[ ! -f "$prev_file" ]]; then
echo "Cannot compare credo, no previous results saved"
fi
if [ ! -d "$credo_dir" ]; then
echo "Creating credo directory: $credo_dir"
mkdir "$credo_dir"
fi;
if [[ $force = true ]] || [[ $is_dirty = true ]] || [[ ! -f "$curr_file" ]]; then
echo ""
echo "Running credo..."
mix credo -a "${credo_args[@]}" > "$curr_file"
# clean up trailing whitespace
sed -i '' 's/[ \t]*$//g' "$curr_file"
# clean up compiling info at beginning of file, so length of files are more comparable
perl -pi -E 's/^(Analysis took |Checking ).*\n//' "$curr_file"
fi
if [[ ! -f "$prev_file" ]]; then
$EDITOR "$curr_file"
else
$DIFF_TOOL "$prev_file" "$curr_file"
fi
keep_x_newest_files "$credo_dir" 15
}
do_dialyzer() {
local curr_file prev_file dialyzer_dir
dialyzer_dir="$check_dir/dialyzer"
prev_file="$dialyzer_dir/dialyzer_$previous_commit_id.txt"
curr_file="$dialyzer_dir/dialyzer_$current_commit_id.txt"
if [[ -f "$prev_file" ]] && [[ $to_dirty == true ]]; then
old_prev="$prev_file"
new_prev="$credo_dir/dialyzer_$previous_commit_id-old.txt"
cp "$old_prev" "$new_prev"
prev_file="$new_prev"
fi
printf "\nDialyzer:\n"
echo "previous_file: $prev_file"
echo "current_file: $curr_file"
if [[ ! -f "$prev_file" ]]; then
echo "Cannot compare dialyzer, no previous results saved"
fi
if [ ! -d "$dialyzer_dir" ]; then
echo "Creating dialyzer directory: $dialyzer_dir"
mkdir "$dialyzer_dir"
fi;
if [[ $force = true ]] || [[ $is_dirty = true ]] || [[ ! -f "$curr_file" ]]; then
echo ""
echo "Running dialyzer..."
# piping to tee prevents dialyzer from adding ansi color codes
mix dialyzer --format=short 2> "$curr_file" | tee
# clean up compiling info at beginning of file, so length of files are more comparable
# perl -pi -E 's/^(Checking PLT|Finding suitable PLTs|Generated |PLT is up to date|Compiling|done in|==>).*\n//' "$curr_file"
# perl -pi -E 's/^.*\.plt\n//' "$curr_file"
fi
if [[ ! -f "$prev_file" ]]; then
$EDITOR "$curr_file"
else
$DIFF_TOOL "$prev_file" "$curr_file"
fi
keep_x_newest_files "$dialyzer_dir" 15
}
print_help() {
cat << $EOS
SYNOPSIS
elixir-check [credo | dialyzer | all] [<options>]
DESCRIPTION
Runs a credo and/or dialyzer for a project and store the result with
a reference to the commit. If you already did this for the previous
commit, it will open a comparison in vscode.
If HEAD has uncommitted changes, the tool will always generate a new
version with the suffix "-dirty".
COMMANDS
credo
Runs credo
dialyzer
Runs dialyzer
all
Runs both credo and dialyzer
OPTIONS
--force
Rerun the command, even if the a cached result is found
--ignore-dirty
Pretend there are not uncommitted changes. This marks the cached results
as the latest commit. It also compares the results to the them to the previous commit instead
the current commit.
--to-dirty
Instead of comparing with the last commit. Compare to the previous dirty
version of the commit
--to <rev>
The commit to compare current results with. The default is the
previous commit. <rev> can be any commit-ish parsable by
\`git rev-parse\`.
--credo-args
Quoted list of arguments you want sent to the 'mix credo' command
$EOS
}
is_dirty=$(check_dirty)
check_dir="_build/checks"
if [ ! -d "$check_dir" ]; then
echo "Creating checks directory: $check_dir"
mkdir "$check_dir"
mkdir "$check_dir/credo"
mkdir "$check_dir/dialyzer"
fi;
command="$1"
shift
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
--help | -h | -\?)
print_help
exit 0
;;
--ignore-dirty)
is_dirty=false
shift
;;
--to-dirty)
to_dirty=true
shift
;;
--to)
if ! previous_commit_id="$(git rev-parse "$2" 2>/dev/null)"; then
echo "error: --to argument could not find unknown reference: '$2'" >&2
exit 1
fi
shift
shift
;;
--force)
force=true
shift
;;
--credo-args)
IFS=' ' read -ra credo_args <<<"$2"
shift
shift
;;
*)
echo "Unknown argument: $key" >&2
echo
echo "run 'elixir-check help' for usage"
exit 1
;;
esac
done
if [ -z "$previous_commit_id" ]; then
previous_commit_id="$(get_previous_commit_id)"
fi
if [ -z "$current_commit_id" ]; then
current_commit_id="$(get_current_commit_id)"
fi
echo "previous_commit_id = $previous_commit_id"
echo "current_commit_id = $current_commit_id"
case "$command" in
credo)
do_credo;;
dialyzer)
do_dialyzer;;
all)
do_credo
do_dialyzer;;
help)
print_help;;
*)
echo "Unknown command: $command" >&2
echo
echo "run 'elixir-check help' for usage"
exit 1
esac
@ohnit
Copy link
Author

ohnit commented Jun 18, 2020

  • When run, it saves credo and dialyzer outputs as text files in a folder in _build
  • The file names contain the commit id in the name
  • Checks if a file exists for the previous commit (or last commit, if you have uncommitted changes) and opens a diff in vscode
  • If there are uncommitted changes, the name will contain "dirty". Dirty states always trigger rerunning of the tools.
  • Auto-deletes the text files. Keeps the most recent 15 files of each type of output

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment