# list all available recipes
default:
  just --list --unsorted

[group('ci')]
[confirm("Do you want to install cargo-sort, cargo-generate and cargo-udeps from crates.io?")]
install-ci-check:
    cargo install cargo-sort
    cargo install cargo-generate
    cargo install cargo-udeps

[group('ci')]
ci-check:
    bash ./ci_checks.sh

[group('automation')]
[confirm("Do you want to bump all fuel maintained dependencies?")]
update-fuel-dependencies:
    bash ./update_fuel_dependencies.sh

[group('automation')]
[confirm("Do you want to automatically update contractIds in this repo?")]
update-contract-ids:
    bash ./test/update-contract-ids.sh

[group('automation')]
bisect-forc path command:
    bash ./scripts/bisect-forc/bisect-forc.sh "{{path}}" "{{command}}"

# The `benchmark` group contains recipes related to benchmarking the Sway compiler, e.g., compilation times.

[group('benchmark')]
benchmark:
    bash ./benchmark.sh

[group('benchmark')]
benchmark-tests:
    bash ./test/bench.sh

# The `performance` group contains recipes related to benchmarking the performance of compiled code:
# gas usages and bytecode sizes.

alias pe2e := perf-e2e
# collect gas usages and bytecode sizes from E2E tests
[group('performance')]
perf-e2e filter='':
    cargo r -r -p test -- --release --kind e2e --perf-only --perf {{filter}}

alias pil := perf-in-lang
# collect gas usages and bytecode sizes from in-language tests
[group('performance')]
perf-in-lang filter='':
    #!/usr/bin/env bash
    branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null); [[ "$branch" == "HEAD" || -z "$branch" ]] && branch="unknown-branch"; branch=${branch//\//-};
    ts="$(date '+%m%d%H%M%S')"
    gas_outfile="./test/perf_out/$ts-in-language-gas-usages-release-$branch.csv"
    size_outfile="./test/perf_out/$ts-in-language-bytecode-sizes-release-$branch.csv"
    filter_args=(); [[ -n "{{filter}}" ]] && filter_args=(--filter "{{filter}}");
    # Capture the test run output once and feed it to both extractors, so the
    # (expensive) test run happens only once.
    tmp="$(mktemp)"; trap 'rm -f "$tmp"' EXIT
    ./test/src/in_language_tests/run_in_language_tests.sh --print-output "${filter_args[@]}" --release | tee /dev/stderr > "$tmp"
    ./scripts/perf/extract-gas-usages.sh < "$tmp" > "$gas_outfile"
    ./scripts/perf/extract-bytecode-sizes.sh < "$tmp" > "$size_outfile"
    echo "Gas usages written to:      $gas_outfile"
    echo "Bytecode sizes written to:  $size_outfile"

alias pst := perf-storage
# run storage benchmarks (storage fields and StorageVec), optionally filtered by project name substring
[group('performance')]
perf-storage filter='':
    ./test/src/e2e_vm_tests/test_programs/should_pass/storage_benchmarks/bench.sh "{{filter}}"

alias pa := perf-all
# collect gas usages and bytecode sizes from all tests (E2E, in-language, and storage)
[group('performance')]
perf-all filter='': (perf-e2e filter) (perf-in-lang filter) (perf-storage filter)

alias pd := perf-diff
# generate performance diff between two CSV files
[group('performance')]
perf-diff before after format='md':
    ./scripts/perf/perf-diff.sh "{{before}}" "{{after}}" "{{format}}"

alias pds := perf-diff-stats
# generate performance statistics summary from a `perf-diff` output CSV file
[group('performance')]
perf-diff-stats diff_file:
    cat "{{diff_file}}" | ./scripts/perf/perf-diff-stats.sh

alias pdl := perf-diff-latest
# generate performance diffs between the latest two CSV files per testing category
[group('performance')]
perf-diff-latest format='md':
    ./scripts/perf/perf-diff-latest.sh "{{format}}"

# This recipe should be used on snapshot tests that contain gas usages from `forc test`.
# It will extract gas usages from versions of the test's `stdout.snap` file
# that are within of the `revision_range`, and output a CSV pivot table
# or an interactive HTML report, depending on the `format`.
# path:           repo path to `stdout.snap` file to extract gas usage from, e.g.: `test/src/e2e_vm_tests/path_to/some_test/stdout.snap`
# revision_range: Git revision range to consider when collecting historic gas usages, e.g.: `HEAD~10..HEAD` (default: all revisions)
# format:         output format, either `csv` or `html` (default: `csv`)
# open:           for `html` output, `-o` opens the report in the default browser

alias psh := perf-snapshot-historical
# collect historic gas usages from a snapshot test that has a `forc test` output
[linux]
[macos]
[group('performance')]
perf-snapshot-historical path revision_range='' format='csv' open='':
    #!/usr/bin/env bash
    if [[ "{{format}}" != "csv" && "{{format}}" != "html" ]]; then
        echo "ERROR: Invalid output format '{{format}}'.  Output format must be either 'csv' or 'html'."
        exit 1
    fi

    now_ts=$(date '+%m%d%H%M%S')
    outfile="./test/perf_out/$now_ts-snapshot-gas-usages-historical-$(basename "$(dirname "{{path}}")")"

    echo "test,gas,commit" > "$outfile.csv"

    for HASH in `git log --format='%H' {{revision_range}} -- {{path}}`; do
        TIMESTAMP=$(git show -s --format='%as-%ct-%H' "$HASH")
        git --no-pager show "$HASH:{{path}}" | bash -c "scripts/perf/extract-gas-usages.sh $TIMESTAMP" >> "$outfile.csv"
    done

    echo "Historical gas usages written to: $outfile.csv"

    if [ "{{format}}" = "html" ]; then
        ./scripts/csv2html/csv2html.sh "$outfile.csv" >> "$outfile.html"
        echo "Pivot table written to:           $outfile.html"
        if [ -n "{{open}}" ]; then
            if which xdg-open &>> /dev/null
            then
                xdg-open "$outfile.html"
            elif which gnome-open &>> /dev/null
            then
                gnome-open "$outfile.html"
            fi
        fi
    else
        pivot_file="./test/perf_out/$now_ts-pivot-snapshot-gas-usages-historical-$(basename "$(dirname "{{path}}")")"
        clipivot max $outfile.csv --rows=test --cols=commit --val=gas > $pivot_file.csv
        echo "Pivot table written to:           $pivot_file.csv"
    fi

alias pl := perf-list
# list all performance files (*gas-usages-*.* and *bytecode-sizes-*.*)
[group('performance')]
perf-list:
    find . -type f \( -name '*-gas-usages-*.*' -o -name '*-bytecode-sizes-*.*' \) -print | sort

alias pr := perf-remove
# remove all performance files (*gas-usages-*.* and *bytecode-sizes-*.*)
[group('performance')]
perf-remove:
    #!/usr/bin/env bash
    files=$(find . -type f \( -name '*-gas-usages-*.*' -o -name '*-bytecode-sizes-*.*' \) -print | sort)

    if [ -z "$files" ]; then
        echo "No performance data files to remove."
        exit 0
    fi

    echo "The following performance data files will be removed:"
    echo "$files"
    echo

    read -r -p 'Do you want to proceed with removing? [y/N] ' yn
    if [[ $yn =~ ^[Yy]$ ]]; then
        echo "Removing..."
        find . -type f \( -name '*-gas-usages-*.*' -o -name '*-bytecode-sizes-*.*' \) -print -delete
    else
        echo "Removing canceled."
    fi

[group('build')]
build-prism:
    cd ./scripts/prism && ./build.sh

[group('build')]
build-highlightjs:
    cd ./scripts/highlightjs && ./build.sh

[group('build')]
generate-sway-lib-std:
    cd ./sway-lib-std && ./generate.sh

alias tfmt := test-forc-fmt-check-panic
# test `forc fmt` for panicking
[group('test')]
test-forc-fmt-check-panic:
    cd ./scripts/formatter && ./forc-fmt-check-panic.sh

alias t := run-tests
# run the full local test suite (pass `--lsp` to also run the sway-lsp tests)
[group('test')]
run-tests *args:
    bash ./scripts/test/run-tests.sh {{args}}