hook: enable calling out of tree entries

in the following setup

├── common
│   ├── .pre-commit-config.yaml
│   ├── script1.sh
│   └── script-config
├── repo1
│   └── code_file
└── repo2
    └── code_file

a common configuration from 'common' folder will be installed using an
absolute path to repo1 and repo2.
As local tools needs to be run (script1.sh with its
configuration script-config) we need to pass the path to common
somehow into the hook cmdline.

Add support for a template variable %CONFIG_BASEPATH% which
is automatically expanded to the configuration directory when
pre-commit run is called

This helps to create a single source of truth setup, while still
keeping the possibility to call non public tools and configurations

Signed-off-by: Konrad Weihmann <kweihmann@outlook.com>
This commit is contained in:
Konrad Weihmann 2022-04-22 09:59:41 +02:00
parent e1ce4c0bf3
commit 91f0344b08
3 changed files with 46 additions and 1 deletions

View file

@ -397,7 +397,7 @@ def run(
config = load_config(config_file)
hooks = [
hook
hook.expand(args, config_file)
for hook in all_hooks(config, store)
if not args.hook or hook.id == args.hook or hook.alias == args.hook
if args.hook_stage in hook.stages

View file

@ -1,6 +1,8 @@
from __future__ import annotations
import argparse
import logging
import os
import shlex
from typing import Any
from typing import NamedTuple
@ -61,5 +63,15 @@ class Hook(NamedTuple):
)
return cls(src=src, prefix=prefix, **{k: dct[k] for k in _KEYS})
def expand(self, args: argparse.Namespace, config_file: str) -> Hook:
map_ = {
'%CONFIG_BASEPATH%': os.path.dirname(os.path.abspath(config_file)),
}
values = self._asdict()
for k, v in map_.items():
values['entry'] = values['entry'].replace(k, v)
values['args'] = [x.replace(k, v) for x in values['args']]
return Hook(**values)
_KEYS = frozenset(set(Hook._fields) - {'src', 'prefix'})