angler-0.1.0 is not a library.
(WIP) Angler: Manage git hooks and run them fast
Plan
- Order steps below
- Simple pre-commit hook
- Shell script hook
-
xargson staged files - Multiple hooks (sequential)
- Rust-based hook (system version)
- From repository
- YAML config
-
installandruncommands - Store
-
uninstall - Python-based hook (system version)
- Python-based hook (dedicated venv)
- Multithread
xargs - Display
- More hook types
- Multithread hooks (non-modifying)
- Lock config
- More languages
Key features
- Fast
- Rust binary, no intermediate VM
- Concurrency across and within hooks
- Pre-computed exact commands to run
- Simple
- Human-readable expansion of each hook
- Local / global install
- No need for a repo-side manifest
- Display only failing hooks
- Monorepo support (?) - Check pre-commit issues
- Sourceable multi-part config (?) - Check pre-commit issues on the matter
- CLI add/remove/stats + autocompletion (?)
Parallel execution
First round: full parallelism
Snapshot Stage
- Take a snapshot of all files to be modified before any hooks run
- This serves as the "base state" that can be restored if needed
Isolated Execution Environment
- Each hook operates on a temporary copy of the files
- Modifications are made to these copies, not the original files
- This prevents partial modifications from being visible to other hooks
Change Recording
- Track all modifications made by each hook
- Store these as "proposed changes" rather than applying them directly
Validation Phase
- After a hook completes, validate that its changes are compatible with changes from other hooks
- Detect potential conflicts (same line modified differently by multiple hooks)
Second round: Sequential Fallback
When conflicts are detected in parallel execution, rather than simply failing or discarding all changes, fall back to sequential. This preserves the automatic fixing behavior users expect.
Smart Ordering
- Learn from conflict patterns to optimize future runs
- Store information about which hooks conflict with each other
- Automatically adjust execution strategy on subsequent runs
Similar tools
Husky
package.json # Modified on running `husky init` to auto-install `husky`
.husky/
.gitignore # Initialized with `*`
pre-commit # Human-writable shell script, initialized with `npm test`
_/ # Configured git.config.core.hooksPath
h # Runs `.husky/<script>` if it exists
pre-commit # Only runs `./husky/_/h`, auto-created
pre-push # Only runs `./husky/_/h`, auto-created
- Configures core hooks path to
.husky/_/ - Writes dummy files for all possible hooks
- Redirects all git hooks to a single dispatcher
h, that runs the appropriate human-written script - Purely shell-based
- Can be disabled using the
HUSKYenvironment variable
Overcommit
TODO
Pre-commit
# project-level
pre-commit-config.yaml
.git/hooks/
pre-commit # Templated, runs `<python> -m pre-commit hook-impl <config> type=pre-commit`
pre-push # Templated, runs `<python> -m pre-commit hook-impl <config> type=pre-push`
# global
~/.cache/pre-commit/
db.db # Store, sqlite DB, tables `repos` [repo, ref, path] and `configs`
repo-<cloned_repo_id>/ # Cached across configs, referenced in the Store
<repo_content> # Cloned from source
.pre-commit-hooks.yaml # Manifest describing how to run the hook, part of the source
<venv> # Contains hook dependencies, created during install
- Structure
- Git hook-level templated block that invokes a dispatcher
- Project-level YAML config
- Global-level cached repo hooks + venv
- Global-level
config -> repos -> pathstore for cleanup - Repo-level manifest (for hook-defining repos)
- Support
- Many languages
- Hooks can require additional dependencies
- Extensible
- Hook-defining repos must expose a manifest
- Local hooks possible
- Install
- Global cache is populated
- Adds templated redirects to a shared dispatcher
- Auto-install possible with template-dir
- Run
- Dispatcher
<python> -m pre-commit hook-impl <config> type=<hook-type>runs- Python process
- Loads config, finds hooks
- Installs missing hooks
- Builds hook commands
- Runs hooks within subprocesses (Python
xargs)
- Concurrency
xargsruns in multithreading- Serial execution can be explicitly required
- Directly invokable with
pre-commit run - Targeted skips possible with
SKIP=environment variable
- Dispatcher