#git-hook #git-workflow #hook #git #workflow #cargo-build #build-script

sloughi

A tiny, no-dependencies crate to make it easy to share and apply git hooks for Rust projects

2 unstable releases

0.3.0 Mar 28, 2022
0.2.0 Mar 28, 2022
0.1.0 Mar 27, 2022

#1583 in Development tools

Apache-2.0

9KB
125 lines

Sloughi

Crates.io

Sloughi Dog

A tiny crate to make it easy to share and apply Git hooks for Rust projects. Inspired by Husky.

  • Zero dependencies.
  • No magic, uses Git's config core.hooksPath to set a custom hooks path. Use native/regular shell scripts for git hooks.
  • Makes use of Cargo's build script.
  • IDE/Code editor agnostic.
  • Customizable setup.

Sloughi is an ancient breed of domesticated dog originating from North Africa (i.e. Algeria, where I live 👋).

Install

  • Add sloughi to your build-dependencies (not dev-dependencies):

    [build-dependencies]
    sloughi = "0.3.0"
    
  • Create a build.rs file at the root of your project to install Sloughi (besides Cargo.toml, not inside src/):

    use sloughi::Sloughi;
    
    fn main() {
        let _ = Sloughi::new().install(); // This will fail silently. Won't interrupt the build.
    }
    

That's it!

The next time cargo build is triggered (by VSCode, or by running cargo run/cargo test), you will notice a .sloughi folder is created with a sample pre-commit hook inside.

Customizing the install

This crate uses the builder pattern, you can chain options on top ::new() to adjust the install:

let _ = Sloughi::new()
    .custom_path(".git_hooks").   // Choose a custom Git hooks relative path (default is ".sloughi")
    .ignore_env("CI").            // Ignore setup when `CI` environment variable is set (like in CircleCI ..etc)
    .ignore_env("GITHUB_ACTIONS") // Do not run in Github Actions as well
    .install();

Fail the build

The above snippets for build.rs will not interrupt the build in case Sloughi install failed (e.g. not a git repo, permission error ..etc). It's explicitly silenced with let _ =, you can handle the error however you like, or just yell with:

Sloughi::new().install().expect("Sloughi install failed");

F.A.Q

Why use build.rs?

Cargo lacks install hooks (like postinstall in npm's package.json), this makes it challenging to have a way to share git hooks automatically in a upstream repository.

Cargo's build script is a nice & transparent way to:

  • Act on the project at build/compile time.
  • Customize the setup without extra config files and formats.

What happens when cargo build is run multiple times?

The install() call is idempotent. It won't modify the existing setup and hooks.

Will this slow down my builds?

No:

  • build.rs itself is only built when it's changed (by default).
  • The setup will first check if you already have .sloughi (or the custom path) created. If so, it skips installs.

Does it run in release mode?

No, release mode is a no-op.

TODO:

  • Optional feature flags. I.e. conventional commits as pre-commit, rustfmt as pre-commit.
  • A [optiona] companion binary to manage hooks.
  • Check Cargo workspaces compatiblity.
  • Introduce the uninstall() call to the exported Sloughi struct.
  • Integration tests.

No runtime deps