jdx / mise

dev tools, env vars, task runner
https://mise.jdx.dev
MIT License
10.29k stars 295 forks source link

Run tasks on git staged files only #2326

Open ramnes opened 5 months ago

ramnes commented 5 months ago

Hey there, thanks for the neat project. :)

I'm using a task as a pre-commit hook, and one thing I'm missing from Python's Pre-commit (pre-commit.com) or other similar tools is the ability to run against staged changes only, and restore the previous state afterwards.

I'd suggest to add a --staged-only option to mise run, similar to what Pre-commit implements here. I think that would pair well with mise generate pre-commit.

What do you think?

jdx commented 5 months ago

I think it depends. I'm open to the idea generally but I wouldn't want to overcomplicate the hook. It would depend on how simple adding this would be.

ramnes commented 5 months ago

The idea behind the --staged-only option I'm proposing to add to mise run is exactly to keep the hook as simple as possible, and hide the complexity behind the CLI. :)

I just hacked something on the repository I'm working on, based on Pre-commit strategy (not heavily tested yet, use at your own risks):

#!/bin/sh
# stashing logic from pre-commit: https://github.com/pre-commit/pre-commit/blob/d56502acabab7910d0ab90f548f2bf469e4d5817/pre_commit/staged_files_only.py
stash_file=".mise/.pre-commit-stash-$(date +%s).diff"

echo "→ Stashing unstaged changes (${stash_file})"
git diff-index --ignore-submodules --binary --exit-code --no-color --no-ext-diff $(git write-tree) > ${stash_file}
git -c submodule.recurse=0 checkout -- .

mise run pre-commit

echo "→ Restoring unstaged changes (${stash_file})"
(git apply --whitespace=nowarn --allow-empty ${stash_file} || git -c core.autocrlf=false apply --whitespace=nowarn --allow-empty ${stash_file}) \
    || (git -c submodule.recurse=0 checkout -- . && git apply --whitespace=nowarn --allow-empty ${stash_file}) \
    && rm ${stash_file}

What I would love is to replace these lines by a simple:

#!/bin/sh
mise run pre-commit --staged-only
jdx commented 5 months ago

I think feature is too specific to one use-case, I think something less impactful like what I sketched in https://github.com/jdx/mise/discussions/2160 would be better

ramnes commented 5 months ago

It's really specific to the use case of pre-commit hooks, but it's a pretty popular one. For reference, Python's Pre-commit is used in at least 186k projects right now :)

I think that 1. your backend system 2. your broad functional coverage and 3. your choice of Rust as a language would make mise a much better tool than Pre-commit for pre-commit hooks, and seeing that you added mise generate git-pre-commit gave me the impression that you saw pre-commit hooks as a logic continuation for mise, but maybe I'm wrong?

FWIW that --staged-only flag I'm talking about could very well be just a tiny wrapper around that CHANGED_FILES environment variable internal handler.

Honestly I have a lot of ideas to make mise the best tool around for pre-commit hooks, so I would love to see your project go that way. :)

PS – Happy to move this to a GitHub Discussion if that makes more sense, or to discuss this anywhere else that's more appropriate.