Skip to content

Commit

Permalink
Add pre-commit wrapper
Browse files Browse the repository at this point in the history
Signed-off-by: Cristian Le <cristian.le@mpsd.mpg.de>
  • Loading branch information
LecrisUT committed Jul 5, 2024
1 parent 64972f2 commit f181b0f
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 4 deletions.
10 changes: 6 additions & 4 deletions .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
- id: tmt-lint
name: tmt lint
entry: bash -c "git ls-files --error-unmatch $(python3 -c 'import tmt; print(tmt.Tree(logger=tmt.Logger.create(), path=\".\").root)')/.fmf/version && tmt lint --failed-only --source $@" PAD
# Use a simple wrapper instead of simply `tmt lint` in order to reorder
# some arguments that need to be passed to `tmt`
entry: python -m tmt._pre_commit --pre-check lint --failed-only --source
files: '(?:.*\.fmf|.*/\.fmf/version)$'
verbose: false
pass_filenames: true
Expand All @@ -9,7 +11,7 @@

- id: tmt-tests-lint
name: tmt tests lint
entry: bash -c "git ls-files --error-unmatch $(python3 -c 'import tmt; print(tmt.Tree(logger=tmt.Logger.create(), path=\".\").root)')/.fmf/version && tmt tests lint --failed-only --source $@" PAD
entry: python -m tmt._pre_commit --pre-check tests lint --failed-only --source
files: '(?:.*\.fmf|.*/\.fmf/version)$'
verbose: false
pass_filenames: true
Expand All @@ -18,7 +20,7 @@

- id: tmt-plans-lint
name: tmt plans lint
entry: bash -c "git ls-files --error-unmatch $(python3 -c 'import tmt; print(tmt.Tree(logger=tmt.Logger.create(), path=\".\").root)')/.fmf/version && tmt plans lint --failed-only --source $@" PAD
entry: python -m tmt._pre_commit --pre-check plans lint --failed-only --source
files: '(?:.*\.fmf|.*/\.fmf/version)$'
verbose: false
pass_filenames: true
Expand All @@ -27,7 +29,7 @@

- id: tmt-stories-lint
name: tmt stories lint
entry: bash -c "git ls-files --error-unmatch $(python3 -c 'import tmt; print(tmt.Tree(logger=tmt.Logger.create(), path=\".\").root)')/.fmf/version && tmt stories lint --failed-only --source $@" PAD
entry: python -m tmt._pre_commit --pre-check stories lint --failed-only --source
files: '(?:.*\.fmf|.*/\.fmf/version)$'
verbose: false
pass_filenames: true
Expand Down
Empty file added tmt/_pre_commit/__init__.py
Empty file.
67 changes: 67 additions & 0 deletions tmt/_pre_commit/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import re
import sys

from tmt.__main__ import run_cli


def _run_precommit() -> None: # pyright: ignore[reportUnusedFunction] (used by project.scripts)
"""
A simple wrapper that re-orders cli arguments before :py:func:`run_cli`.
This utility is needed in order to move arguments like ``--root`` before
the ``lint`` keyword when run by ``pre-commit``.
Only a limited number of arguments are reordered.
"""

# Only re-ordering a few known/necessary cli arguments of `main` command
# Could be improved if the click commands can be introspected like with
# `attrs.fields`
# https://github.com/pallets/click/issues/2709

argv = sys.argv
# Get the last argument that starts with `-`. Other inputs after that are
# assumed to be filenames (which can be thousands of them)
for last_arg in reversed(range(len(argv))):
if argv[last_arg].startswith("-"):
break
else:
# If there were no args passed, then just `run_cli`
run_cli()
return

# At this point we need to check and re-order the arguments if needed
for pattern, nargs in [
(r"(--root$|-r)", 1),
(r"(--root=.*)", 0),
(r"(--verbose$|-v+)", 0),
(r"(--debug$|-d+)", 0),
(r"(--pre-check$)", 0),
]:
if any(match := re.match(pattern, arg) for arg in argv[1:last_arg + 1]):
assert match
# Actual argument matched
actual_arg = match.group(1)
indx = argv.index(actual_arg)
# Example of reorder args:
# ["tmt", "tests", "lint", "--fix", "--root", "/some/path", "some_file"]
# - argv[0]: name of the program is always first
# ["tmt"]
# - argv[indx:indx+1+nargs]: args to move (pass to `tmt.cli.main`)
# ["--root", "/some/path"]
# - argv[1:indx]: all other keywords (`lint` keyword is in here)
# ["tests", "lint", "--fix"]
# - argv[indx+1+nargs:]: All remaining keywords
# ["some_file"]
# After reorder:
# ["tmt", "--root", "/some/path", "tests", "lint", "--fix", "some_file"]
argv = (
argv[0:1] + argv[indx: indx + 1 + nargs] + argv[1:indx] + argv[indx + 1 + nargs:]
)
# Finally move the reordered args to sys.argv and run the cli
sys.argv = argv
run_cli()


if __name__ == "__main__":
_run_precommit()
17 changes: 17 additions & 0 deletions tmt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,18 @@ def write_dl(
'--force-color', is_flag=True, default=False,
help='Forces tmt to use colors in the output and logging.'
)
@option(
'--pre-check', is_flag=True, default=False, hidden=True,
help='Run pre-checks on the git root. (Used by pre-commit wrapper).'
)
def main(
click_contex: Context,
root: str,
context: list[str],
no_color: bool,
force_color: bool,
show_time: bool,
pre_check: bool,
**kwargs: Any) -> None:
""" Test Management Tool """

Expand All @@ -339,6 +344,18 @@ def main(
# Save click context and fmf context for future use
tmt.utils.Common.store_cli_invocation(click_contex)

# Run pre-checks
if pre_check:
git_command = tmt.utils.Command('git', 'rev-parse', '--show-toplevel')
git_root = git_command.run(cwd=None, logger=logger).stdout
if not git_root:
raise tmt.utils.RunError("git rev-parse did not produce a path", git_command, 0)
git_root = git_root.strip()
git_command = tmt.utils.Command(
'git', 'ls-files', '--error-unmatch', f"{git_root}/{root}/.fmf/version"
)
git_command.run(cwd=None, logger=logger)

# Initialize metadata tree (from given path or current directory)
tree = tmt.Tree(logger=logger, path=Path(root))

Expand Down

0 comments on commit f181b0f

Please sign in to comment.