DEV Community

Milo
Milo

Posted on

Imagine Git hooks in Rust..

I'm going to say it.... Git hooks are bad.

Well, not bad, just annoying, and way too much setup. You have to write a bash script, etc, and things like husky simplify it.. but not enough.

I wrote something a few months ago called Glitter, with its sole purpose being a commit message templating system. It works fantastic, but recently I had someone create an issue: https://github.com/Milo123459/glitter/issues/33

They basically asked for Git Hooks in Glitter. I'd already implemented a task system (so you could do something like glitter fmt or glitter cc fmt) just by using a simple bit of config, but I thought that just like the user suggested, automatically running them before git add . in the push command.

Some benefits:

  • Git Hooks can be quite slow
  • Git Hooks can sometimes not pick up paths of packages installed with npm
  • Simple config, and can be setup in less than 30 seconds

So lets look at something to format our Rust code before we push.

{
  ...
    "custom_tasks": [
        {
            "name": "fmt",
            "execute": [
                "cargo fmt"
            ]
        },
        {
            "name": "lint",
            "execute": [
                "cargo clippy --all-features --all-targets"
            ]
        }
    ],
    "hooks": [
        "fmt",
        "lint"
    ]
}
Enter fullscreen mode Exit fullscreen mode

... is other config. Check out this post if you want to know how to initially set it up.

Right, it's quite a lot to take in, lets break it down.

custom_tasks are tasks that we can run, or, alternatively, can be used as hooks. From this example, I can do glitter fmt (or glitter cc fmt) and it'll run cargo fmt. If I ran glitter lint (or glitter cc lint) it'll run cargo clippy --all-features --all-targets, and so on.

We can then reference these tasks in the hooks field. This field takes in the name of your tasks and will just run the commands specified in the execute field.

Problems I faced

Things like yarn (or any NPM package installed with npm globally) wouldn't be picked up in the path. I was able to fix this rather simply by using the crate which which allows me to get a path to an executable (or a shell script) to run to run the cli. This can also sometimes be a bit faster than just running the name of the command (ie, it'll be faster if I provide a path to yarn, and don't run yarn itself)

Additional info

Hooks will exit and cancel the command if the command fails or it's exit code is not 0. It's very simple.

If you feel this is cool, please leave a star on the repo.

Feature requests can be put in issues on the repo if possible. If you have any questions, you can make a discussion or ask in the comments.

Thanks!

Top comments (0)