diff --git a/.config/flakebox/id b/.config/flakebox/id new file mode 100644 index 0000000..1b3aea9 --- /dev/null +++ b/.config/flakebox/id @@ -0,0 +1 @@ +4bef2ccb693617da03555f48eb47b0a1521eff57b107f63ef255e94e0518216ec12e293bd8a1551c6d7283294e6c467ba77bc669e7e14e79006eb74d87fd13f4 diff --git a/.config/flakebox/shellHook.sh b/.config/flakebox/shellHook.sh new file mode 100644 index 0000000..4653f3a --- /dev/null +++ b/.config/flakebox/shellHook.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +dot_git="$(git rev-parse --git-common-dir)" +if [[ ! -d "${dot_git}/hooks" ]]; then mkdir -p "${dot_git}/hooks"; fi +rm -f "${dot_git}/hooks/commit-msg" +ln -sf "$(pwd)/misc/git-hooks/commit-msg" "${dot_git}/hooks/commit-msg" + +dot_git="$(git rev-parse --git-common-dir)" +if [[ ! -d "${dot_git}/hooks" ]]; then mkdir -p "${dot_git}/hooks"; fi +rm -f "${dot_git}/hooks/pre-commit" +ln -sf "$(pwd)/misc/git-hooks/pre-commit" "${dot_git}/hooks/pre-commit" + +# set template +git config commit.template misc/git-hooks/commit-template.txt + +if [ -n "${DIRENV_IN_ENVRC:-}" ]; then + # and not set DIRENV_LOG_FORMAT + if [ -n "${DIRENV_LOG_FORMAT:-}" ]; then + >&2 echo "💡 Set 'DIRENV_LOG_FORMAT=\"\"' in your shell environment variables for a cleaner output of direnv" + fi +fi + +>&2 echo "💡 Run 'just' for a list of available 'just ...' helper recipes" diff --git a/.config/semgrep.yaml b/.config/semgrep.yaml new file mode 100644 index 0000000..e69de29 diff --git a/.github/workflows/flakebox-ci.yml b/.github/workflows/flakebox-ci.yml new file mode 100644 index 0000000..daa903d --- /dev/null +++ b/.github/workflows/flakebox-ci.yml @@ -0,0 +1,76 @@ +# THIS FILE IS AUTOGENERATED FROM FLAKEBOX CONFIGURATION + +jobs: + build: + name: Build + runs-on: ${{ matrix.runs-on }} + steps: + - uses: actions/checkout@v4 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@v4 + - name: Magic Nix Cache + uses: DeterminateSystems/magic-nix-cache-action@v2 + - name: Build on ${{ matrix.host }} + run: nix build .#ci.rblake2sum + strategy: + matrix: + host: + - macos + - linux + include: + - host: linux + runs-on: ubuntu-latest + timeout: 60 + - host: macos + runs-on: macos-12 + timeout: 60 + timeout-minutes: ${{ matrix.timeout }} + flake: + name: Flake self-check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Check Nix flake inputs + uses: DeterminateSystems/flake-checker-action@v5 + with: + fail-mode: true + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@v4 + - name: Magic Nix Cache + uses: DeterminateSystems/magic-nix-cache-action@v2 + - name: Cargo Cache + uses: actions/cache@v3 + with: + key: ${{ runner.os }}-${{ hashFiles('Cargo.lock') }} + path: ~/.cargo + - name: Commit Check + run: '# run the same check that git `pre-commit` hook does + + nix develop --ignore-environment .# --command ./misc/git-hooks/pre-commit + + ' +name: CI +'on': + merge_group: + branches: + - master + - main + pull_request: + branches: + - master + - main + push: + branches: + - master + - main + tags: + - v* + workflow_dispatch: {} + + +# THIS FILE IS AUTOGENERATED FROM FLAKEBOX CONFIGURATION diff --git a/.github/workflows/flakebox-flakehub-publish.yml b/.github/workflows/flakebox-flakehub-publish.yml new file mode 100644 index 0000000..badbeec --- /dev/null +++ b/.github/workflows/flakebox-flakehub-publish.yml @@ -0,0 +1,34 @@ +# THIS FILE IS AUTOGENERATED FROM FLAKEBOX CONFIGURATION + +jobs: + flakehub-publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: '${{ (inputs.tag != null) && format(''refs/tags/{0}'', inputs.tag) || + '''''' }} + + ' + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@v4 + - name: Flakehub Push + uses: DeterminateSystems/flakehub-push@main + with: + name: ${{ github.repository }} + tag: ${{ inputs.tag }} + visibility: public +name: Publish to Flakehub +'on': + push: + tags: + - v?[0-9]+.[0-9]+.[0-9]+* + workflow_dispatch: + inputs: + tags: + description: The existing tag to publish to FlakeHub + required: true + type: string + + +# THIS FILE IS AUTOGENERATED FROM FLAKEBOX CONFIGURATION diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..b32175c --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,4 @@ +group_imports = "StdExternalCrate" +wrap_comments = true +format_code_in_doc_comments = true +imports_granularity = "Module" diff --git a/Cargo.toml b/Cargo.toml index a6bd5f8..ccc127a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,3 +18,23 @@ blake2 = "0.10.6" crev-recursive-digest = { version = "0.6.0" } hex = "0.4" clap = { version = "4.2.7", features = ["derive"] } + + +[profile.release] +lto = "fat" +codegen-units = 1 +strip = true + +[profile.ci] +inherits = "dev" +debug = 1 +incremental = false + +# Workaround: https://github.com/rust-lang/cargo/issues/12457 which causes +# https://github.com/ipetkov/crane/issues/370 +[profile.dev.build-override] +debug = false +[profile.ci.build-override] +debug = false +[profile.release.build-override] +debug = false diff --git a/ci/prep_deploy.sh b/ci/prep_deploy.sh index 9def7e4..1131bcc 100755 --- a/ci/prep_deploy.sh +++ b/ci/prep_deploy.sh @@ -10,5 +10,5 @@ cp rblake2sum/README.md LICENSE* "$name/" tar czvf "$name.tar.gz" "$name" # Get the sha-256 checksum w/o filename and newline -echo -n $(shasum -ba 256 "$name.tar.gz" | cut -d " " -f 1) > "$name.tar.gz.sha256" +echo -n "$(shasum -ba 256 "$name.tar.gz" | cut -d " " -f 1)" > "$name.tar.gz.sha256" diff --git a/ci/travis-musl-openssl.sh b/ci/travis-musl-openssl.sh index f2487b8..28c60e0 100755 --- a/ci/travis-musl-openssl.sh +++ b/ci/travis-musl-openssl.sh @@ -6,7 +6,7 @@ case "$TARGET" in OPTIONS=(linux-x86_64) ;; i686-*) - OPTIONS=(linux-generic32 -m32 -Wl,-melf_i386) + OPTIONS=(linux-generic32 -m32 "-Wl,-melf_i386") ;; esac diff --git a/flake.lock b/flake.lock index 52122e2..618b242 100644 --- a/flake.lock +++ b/flake.lock @@ -1,41 +1,91 @@ { "nodes": { + "android-nixpkgs": { + "inputs": { + "devshell": "devshell", + "flake-utils": "flake-utils_2", + "nixpkgs": [ + "flakebox", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1695500413, + "narHash": "sha256-yinrAWIc4XZbWQoXOYkUO0lCNQ5z/vMyl+QCYuIwdPc=", + "owner": "dpc", + "repo": "android-nixpkgs", + "rev": "2e42268a196375ce9b010a10ec5250d2f91a09b4", + "type": "github" + }, + "original": { + "owner": "dpc", + "repo": "android-nixpkgs", + "rev": "2e42268a196375ce9b010a10ec5250d2f91a09b4", + "type": "github" + } + }, "crane": { "inputs": { "flake-compat": "flake-compat", - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_3", "nixpkgs": [ + "flakebox", "nixpkgs" ], "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1666567222, - "narHash": "sha256-AVySilLW+eNM409GSIJYsF6wg5NsxK12Ht2DMSYAgO0=", - "owner": "ipetkov", + "lastModified": 1696222002, + "narHash": "sha256-2xCGgEXOIJsaS6zFUhST/t7kiroMofjViw01w65JEfs=", + "owner": "dpc", "repo": "crane", - "rev": "2ce1a3313e299b0db63b11f94c863af74b0b08ad", + "rev": "bf5f4b71b446e5784900ee9ae0f2569e5250e360", "type": "github" }, "original": { - "owner": "ipetkov", + "owner": "dpc", "repo": "crane", + "rev": "bf5f4b71b446e5784900ee9ae0f2569e5250e360", + "type": "github" + } + }, + "devshell": { + "inputs": { + "nixpkgs": [ + "flakebox", + "android-nixpkgs", + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1695195896, + "narHash": "sha256-pq9q7YsGXnQzJFkR5284TmxrLNFc0wo4NQ/a5E93CQU=", + "owner": "numtide", + "repo": "devshell", + "rev": "05d40d17bf3459606316e3e9ec683b784ff28f16", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", "type": "github" } }, "fenix": { "inputs": { "nixpkgs": [ + "flakebox", "nixpkgs" ], "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1666766063, - "narHash": "sha256-5xc/eoUZSUbEt+PKQgICpiSY4L2BCfttjQhjNTa+EPk=", + "lastModified": 1695104496, + "narHash": "sha256-B+itawD+o58jjolphhMLnSvtY6aPAZtExE24Eqq5FBA=", "owner": "nix-community", "repo": "fenix", - "rev": "0748dc3f419917e3548419e91839ee062e1a88fb", + "rev": "82619f17173aae0216eedd589445541a7804ba4e", "type": "github" }, "original": { @@ -47,11 +97,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", "owner": "edolstra", "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", "type": "github" }, "original": { @@ -76,12 +126,51 @@ } }, "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, "locked": { - "lastModified": 1659877975, - "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "owner": "numtide", "repo": "flake-utils", - "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", "type": "github" }, "original": { @@ -90,38 +179,79 @@ "type": "github" } }, + "flakebox": { + "inputs": { + "android-nixpkgs": "android-nixpkgs", + "crane": "crane", + "fenix": "fenix", + "flake-utils": "flake-utils_4", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-unstable": "nixpkgs-unstable" + }, + "locked": { + "lastModified": 1696567182, + "narHash": "sha256-urBaztEDSLR+P+XTGW2LNcZ/6fRWbaLEB0GjnDD8k4w=", + "owner": "rustshop", + "repo": "flakebox", + "rev": "dd64cdf2a19a1f5241c68f3220139f4a9cbdb01e", + "type": "github" + }, + "original": { + "owner": "rustshop", + "repo": "flakebox", + "rev": "dd64cdf2a19a1f5241c68f3220139f4a9cbdb01e", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1666610816, - "narHash": "sha256-q4F2VNe5bpxXOvp16DyLwE1SgNZMbNO29ZQJPIomedg=", + "lastModified": 1696374741, + "narHash": "sha256-gt8B3G0ryizT9HSB4cCO8QoxdbsHnrQH+/BdKxOwqF0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6107f97012a0c134c5848125b5aa1b149b76d2c9", + "rev": "8a4c17493e5c39769f79117937c79e1c88de6729", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-22.05", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1696193975, + "narHash": "sha256-mnQjUcYgp9Guu3RNVAB2Srr1TqKcPpRXmJf4LJk6KRY=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "fdd898f8f79e8d2f99ed2ab6b3751811ef683242", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, "root": { "inputs": { - "crane": "crane", - "fenix": "fenix", - "flake-utils": "flake-utils_2", + "flake-utils": "flake-utils", + "flakebox": "flakebox", "nixpkgs": "nixpkgs" } }, "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1666620525, - "narHash": "sha256-XL/8MDKydIni4ObTvuXBOVT+i87TLlutFPxYcd0Cy8I=", + "lastModified": 1695027950, + "narHash": "sha256-u4lq0LBmXqEfppyeYQqg6w+4Abk2qDnmsPEF+C2xFdQ=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "53b6d69e931a52cca44ef94c3b713b4d255754b8", + "rev": "258b15c506a2d3ad862fd17ae24eaf272443f477", "type": "github" }, "original": { @@ -134,20 +264,22 @@ "rust-overlay": { "inputs": { "flake-utils": [ + "flakebox", "crane", "flake-utils" ], "nixpkgs": [ + "flakebox", "crane", "nixpkgs" ] }, "locked": { - "lastModified": 1666494036, - "narHash": "sha256-4mmm+1MBPMD56LMLN9QcEwnfnu41NkA6lDeZGjSrxIw=", + "lastModified": 1683080331, + "narHash": "sha256-nGDvJ1DAxZIwdn6ww8IFwzoHb2rqBP4wv/65Wt5vflk=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "af2e939ba2c7cbb188d06d6650c6353b10b3f2be", + "rev": "d59c3fa0cba8336e115b376c2d9e91053aa59e56", "type": "github" }, "original": { @@ -155,6 +287,66 @@ "repo": "rust-overlay", "type": "github" } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 2543576..37e3578 100644 --- a/flake.nix +++ b/flake.nix @@ -1,74 +1,62 @@ { - description = "dpc's basic flake template"; + description = "A recursive blake2 digest (hash) of a file-system path"; inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.05"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.05"; flake-utils.url = "github:numtide/flake-utils"; - crane.url = "github:ipetkov/crane"; - crane.inputs.nixpkgs.follows = "nixpkgs"; - fenix = { - url = "github:nix-community/fenix"; + flakebox = { + url = "github:rustshop/flakebox?rev=dd64cdf2a19a1f5241c68f3220139f4a9cbdb01e"; inputs.nixpkgs.follows = "nixpkgs"; }; }; - outputs = { self, nixpkgs, flake-utils, crane, fenix }: + outputs = { self, nixpkgs, flake-utils, flakebox }: flake-utils.lib.eachDefaultSystem (system: let - pkgs = import nixpkgs { - inherit system; - }; - lib = pkgs.lib; - fenixChannel = fenix.packages.${system}.stable; - fenixToolchain = (fenixChannel.withComponents [ - "rustc" - "cargo" - "clippy" - "rust-analysis" - "rust-src" - "rustfmt" - ]); - craneLib = crane.lib.${system}.overrideToolchain fenixToolchain; + projectName = "rblake2sum"; - commonArgs = { - src = craneLib.cleanCargoSource ./.; + flakeboxLib = flakebox.lib.${system} { + config = { + github.ci.buildOutputs = [ ".#ci.rblake2sum" ]; + typos.pre-commit.enable = false; + }; + }; - buildInputs = with pkgs; [ - ]; + buildPaths = [ + "Cargo.toml" + "Cargo.lock" + ".cargo" + "src" + ]; - nativeBuildInputs = with pkgs; [ - ]; + buildSrc = flakeboxLib.filterSubPaths { + root = builtins.path { + name = projectName; + path = ./.; + }; + paths = buildPaths; }; + + multiBuild = + (flakeboxLib.craneMultiBuild { }) (craneLib': + let + craneLib = (craneLib'.overrideArgs { + pname = "flexbox-multibuild"; + src = buildSrc; + }); + in + { + rblake2sum = craneLib.buildPackage { }; + }); in { - packages.default = craneLib.buildPackage ({ } // commonArgs); + packages.default = multiBuild.rblake2sum; - devShells = { - default = pkgs.mkShell { - - buildInputs = with pkgs; [ ] ++ commonArgs.buildInputs; - nativeBuildInputs = with pkgs; [ - fenix.packages.${system}.rust-analyzer - fenixToolchain - cargo-udeps - - # This is required to prevent a mangled bash shell in nix develop - # see: https://discourse.nixos.org/t/interactive-bash-with-nix-develop-flake/15486 - (hiPrio pkgs.bashInteractive) + legacyPackages = multiBuild; - # Nix - pkgs.nixpkgs-fmt - pkgs.shellcheck - pkgs.rnix-lsp - pkgs.nodePackages.bash-language-server - - ] ++ commonArgs.nativeBuildInputs; - shellHook = '' - dot_git="$(git rev-parse --git-common-dir)" - if [[ ! -d "$dot_git/hooks" ]]; then mkdir "$dot_git/hooks"; fi - for hook in misc/git-hooks/* ; do ln -sf "$(pwd)/$hook" "$dot_git/hooks/" ; done - ${pkgs.git}/bin/git config commit.template $(pwd)/misc/git-hooks/commit-template.txt - ''; + devShells = { + default = flakeboxLib.mkDevShell { + packages = [ ]; }; }; } diff --git a/justfile b/justfile new file mode 100644 index 0000000..de8cabe --- /dev/null +++ b/justfile @@ -0,0 +1,86 @@ +# THIS FILE IS AUTOGENERATED FROM FLAKEBOX CONFIGURATION +alias b := build +alias c := check +alias t := test + + +[private] +default: + @just --list + + +# run `cargo build` on everything +build: + cargo build --workspace --all-targets + + +# run `cargo check` on everything +check: + cargo check --workspace --all-targets + + +# run all checks recommended before opening a PR +final-check: lint clippy + cargo test --doc + just test + + +# run code formatters +format: + cargo fmt --all + nixpkgs-fmt $(echo **.nix) + + +# run lints (git pre-commit hook) +lint: + env NO_STASH=true $(git rev-parse --git-common-dir)/hooks/pre-commit + + +# run tests +test: build + cargo test + + +# run and restart on changes +watch: + env RUST_LOG=${RUST_LOG:-debug} cargo watch -x run + + +# run `cargo clippy` on everything +clippy: + cargo clippy --workspace --all-targets -- --deny warnings --allow deprecated + +# run `cargo clippy --fix` on everything +clippy-fix: + cargo clippy --workspace --all-targets --fix + + +# run `semgrep` +semgrep: + env SEMGREP_ENABLE_VERSION_CHECK=0 \ + semgrep --error --config .config/semgrep.yaml + + +# check typos +[no-exit-message] +typos *PARAMS: + #!/usr/bin/env bash + set -eo pipefail + + export FLAKEBOX_GIT_LS + FLAKEBOX_GIT_LS="$(git ls-files)" + export FLAKEBOX_GIT_LS_TEXT + FLAKEBOX_GIT_LS_TEXT="$(echo "$FLAKEBOX_GIT_LS" | grep -v -E "^db/|\.(png|ods|jpg|jpeg|woff2|keystore|wasm|ttf|jar|ico)\$")" + + + if ! echo "$FLAKEBOX_GIT_LS_TEXT" | typos {{PARAMS}} --stdin-paths; then + >&2 echo "Typos found: Valid new words can be added to '.typos.toml'" + return 1 + fi + +# fix all typos +[no-exit-message] +typos-fix-all: + just typos -w + +# THIS FILE IS AUTOGENERATED FROM FLAKEBOX CONFIGURATION diff --git a/misc/git-hooks/commit-msg b/misc/git-hooks/commit-msg new file mode 100755 index 0000000..ba85b62 --- /dev/null +++ b/misc/git-hooks/commit-msg @@ -0,0 +1,23 @@ +#!/nix/store/8fv91097mbh5049i9rglc73dx6kjg3qk-bash-5.2-p15/bin/bash +# Sanitize file first, by removing leading lines that are empty or start with a hash, +# as `convco` currently does not do it automatically (but git will) +# TODO: next release of convco should be able to do it automatically +MESSAGE="$( + while read -r line ; do + # skip any initial comments (possibly from previous run) + if [ -z "${body_detected:-}" ] && { [[ "$line" =~ ^#.*$ ]] || [ "$line" == "" ]; }; then + continue + fi + body_detected="true" + + echo "$line" + done < "$1" +)" + +# convco fails on fixup!, so remove fixup! prefix +MESSAGE="${MESSAGE#fixup! }" +if ! convco check --from-stdin <<<"$MESSAGE" ; then + >&2 echo "Please follow conventional commits(https://www.conventionalcommits.org)" + >&2 echo "Use git recommit to fix your commit" + exit 1 +fi diff --git a/misc/git-hooks/pre-commit b/misc/git-hooks/pre-commit index 7550a18..6926c33 100755 --- a/misc/git-hooks/pre-commit +++ b/misc/git-hooks/pre-commit @@ -1,23 +1,154 @@ +#!/nix/store/8fv91097mbh5049i9rglc73dx6kjg3qk-bash-5.2-p15/bin/bash #!/usr/bin/env bash -set -eo pipefail - -# Revert `git stash` on exit -function revert_git_stash { - >&2 echo "Unstashing uncommited changes..." - git stash pop -q -} +set -euo pipefail set +e git diff-files --quiet is_unclean=$? set -e +# Revert `git stash` on exit +function revert_git_stash { + >&2 echo "Unstashing uncommitted changes..." + git stash pop -q +} + # Stash pending changes and revert them when script ends -if [ $is_unclean -ne 0 ]; then - >&2 echo "Stashing uncommited changes..." - git stash -q --keep-index +if [ -z "${NO_STASH:-}" ] && [ $is_unclean -ne 0 ]; then + >&2 echo "Stashing uncommitted changes..." + GIT_LITERAL_PATHSPECS=0 git stash -q --keep-index trap revert_git_stash EXIT fi -# TODO: add checks below +export FLAKEBOX_GIT_LS +FLAKEBOX_GIT_LS="$(git ls-files)" +export FLAKEBOX_GIT_LS_TEXT +FLAKEBOX_GIT_LS_TEXT="$(echo "$FLAKEBOX_GIT_LS" | grep -v -E "^db/|\.(png|ods|jpg|jpeg|woff2|keystore|wasm|ttf|jar|ico)\$")" + + +function check_nothing() { + true +} +export -f check_nothing + +function check_cargo_fmt() { + set -euo pipefail + + cargo fmt --all --check + +} +export -f check_cargo_fmt + +function check_cargo_lock() { + set -euo pipefail + + # https://users.rust-lang.org/t/check-if-the-cargo-lock-is-up-to-date-without-building-anything/91048/5 + cargo update --workspace --locked + +} +export -f check_cargo_lock + +function check_leftover_dbg() { + set -euo pipefail + + errors="" + for path in $(echo "$FLAKEBOX_GIT_LS_TEXT" | grep '.*\.rs'); do + if grep 'dbg!(' "$path" > /dev/null; then + >&2 echo "$path contains dbg! macro" + errors="true" + fi + done + + if [ -n "$errors" ]; then + >&2 echo "Fix the problems above or use --no-verify" 1>&2 + return 1 + fi + +} +export -f check_leftover_dbg + +function check_semgrep() { + set -euo pipefail + + # semgrep is not available on MacOS + if ! command -v semgrep > /dev/null ; then + >&2 echo "Skipping semgrep check: not available" + return 0 + fi + + if [ ! -f .config/semgrep.yaml ] ; then + >&2 echo "Skipping semgrep check: .config/semgrep.yaml doesn't exist" + return 0 + fi + + if [ ! -s .config/semgrep.yaml ] ; then + >&2 echo "Skipping semgrep check: .config/semgrep.yaml empty" + return 0 + fi + + env SEMGREP_ENABLE_VERSION_CHECK=0 \ + semgrep -q --error --config .config/semgrep.yaml + +} +export -f check_semgrep + +function check_shellcheck() { + set -euo pipefail + + for path in $(echo "$FLAKEBOX_GIT_LS_TEXT" | grep -E '.*\.sh$'); do + shellcheck --severity=warning "$path" + done + +} +export -f check_shellcheck + +function check_trailing_newline() { + set -euo pipefail + + errors="" + for path in $(echo "$FLAKEBOX_GIT_LS_TEXT"); do + + # extra branches for clarity + if [ ! -s "$path" ]; then + # echo "$path is empty" + true + elif [ -z "$(tail -c 1 < "$path")" ]; then + # echo "$path ends with a newline or with a null byte" + true + else + >&2 echo "$path doesn't end with a newline" 1>&2 + errors="true" + fi + done + + if [ -n "$errors" ]; then + >&2 echo "Fix the problems above or use --no-verify" 1>&2 + return 1 + fi + +} +export -f check_trailing_newline + +function check_trailing_whitespace() { + set -euo pipefail + + if ! git diff --check HEAD ; then + echo "Trailing whitespace detected. Please remove them before committing." + return 1 + fi + +} +export -f check_trailing_whitespace + +parallel \ + --nonotice \ +::: \ + check_cargo_fmt \ + check_cargo_lock \ + check_leftover_dbg \ + check_semgrep \ + check_shellcheck \ + check_trailing_newline \ + check_trailing_whitespace \ + check_nothing diff --git a/src/opts.rs b/src/opts.rs index de59648..093d3bd 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -1,6 +1,7 @@ -use clap::Parser; use std::path::PathBuf; +use clap::Parser; + #[derive(Parser, Debug, Clone)] #[command(author, version, about, long_about = None)] pub struct Opts {