mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-04-16 02:21:46 +04:00
POC or MVP: Succeeds checking shfmt on Windows which uses bash. Requires that bash is meaningful (WSL, MSys64) on the command prompt, and shfmt is installed in the bash environment.
This commit is contained in:
parent
023b337ff0
commit
e7698cdb38
4 changed files with 102 additions and 2 deletions
|
|
@ -40,3 +40,11 @@ repos:
|
|||
hooks:
|
||||
- id: check-hooks-apply
|
||||
- id: check-useless-excludes
|
||||
# Requires to be run under `bash`.
|
||||
# Requires installation of additional tools. Tools are available on Windows.
|
||||
# shfmt: https://github.com/mvdan/sh/releases
|
||||
- repo: https://github.com/syntaqx/git-hooks
|
||||
rev: v0.0.16
|
||||
hooks:
|
||||
- id: shfmt
|
||||
args: [-i 4, -w, -s]
|
||||
|
|
|
|||
2
bash_script.sh
Normal file
2
bash_script.sh
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/bash
|
||||
set -Eeuo pipefail
|
||||
85
pre_commit/ShelPathConv.py
Normal file
85
pre_commit/ShelPathConv.py
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
#!/usr/bin/env python3
|
||||
"""."""
|
||||
import glob
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
GLOB_PATTERN = re.compile(r'([^:/\\])(?=[/\\]|$)')
|
||||
|
||||
|
||||
def GetRealCasePath(path):
|
||||
"""Convert a case preserving path to a case sensitive compatible path."""
|
||||
drive, tail = os.path.splitdrive(path)
|
||||
return next(
|
||||
iter(glob.glob(''.join((drive, re.sub(GLOB_PATTERN, r'[\1]', tail))))),
|
||||
path,
|
||||
)
|
||||
|
||||
|
||||
def ConvertPath(path, prefix, drive_letter_case):
|
||||
"""Convert a Windows path to a POSIX path."""
|
||||
if os.path.exists(path):
|
||||
path = GetRealCasePath(path)
|
||||
drive, tail = os.path.splitdrive(path)
|
||||
if drive and not os.path.isabs(path):
|
||||
drive, tail = os.path.splitdrive(os.path.abspath(path))
|
||||
if drive and drive[1:2] == r':':
|
||||
path = (
|
||||
prefix /
|
||||
drive_letter_case(drive[0]) /
|
||||
pathlib.PureWindowsPath(tail[1:]).as_posix()
|
||||
).as_posix()
|
||||
else:
|
||||
path = pathlib.PureWindowsPath(path).as_posix()
|
||||
return path
|
||||
|
||||
|
||||
def ConvertArgsWin32(*args):
|
||||
"""Convert all path like arguments from Windows to POSIX."""
|
||||
path = os.path.abspath(os.environ.get('SystemRoot'))
|
||||
if not path or path[1:2] != r':':
|
||||
return args
|
||||
|
||||
try:
|
||||
nix_path = subprocess.run(
|
||||
[args[0], '-c', 'pwd'],
|
||||
check=True,
|
||||
cwd=path,
|
||||
stdout=subprocess.PIPE,
|
||||
universal_newlines=True,
|
||||
).stdout.strip()
|
||||
except Exception:
|
||||
return args
|
||||
|
||||
path = pathlib.PureWindowsPath(
|
||||
os.path.splitdrive(GetRealCasePath(path))[1],
|
||||
).as_posix()
|
||||
prefix, nix_path, tail = (
|
||||
pathlib.PurePosixPath(nix_path).as_posix().partition(path)
|
||||
)
|
||||
if not prefix or nix_path != path or tail:
|
||||
return args
|
||||
|
||||
drive_letter_case = (
|
||||
(lambda s: s.upper())
|
||||
if prefix[-1:].isupper()
|
||||
else (lambda s: s.lower())
|
||||
if prefix[-1:].islower()
|
||||
else (lambda s: s)
|
||||
)
|
||||
prefix = pathlib.PurePosixPath(prefix[0:-1])
|
||||
|
||||
return [args[0]] + [
|
||||
ConvertPath(arg, prefix, drive_letter_case) for arg in args[1:]
|
||||
]
|
||||
|
||||
|
||||
ConvertArgs = (
|
||||
ConvertArgsWin32 if sys.platform == 'win32' else (lambda *args: args)
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(*ConvertArgs(*sys.argv[1:]))
|
||||
|
|
@ -4,6 +4,9 @@ from __future__ import unicode_literals
|
|||
import os.path
|
||||
|
||||
from identify.identify import parse_shebang_from_file
|
||||
from identify.identify import tags_from_path
|
||||
|
||||
from pre_commit import ShelPathConv
|
||||
|
||||
|
||||
class ExecutableNotFoundError(OSError):
|
||||
|
|
@ -71,10 +74,12 @@ def normalize_cmd(cmd):
|
|||
# Use PATH to determine the executable
|
||||
exe = normexe(cmd[0])
|
||||
|
||||
convert = 'shell' in tags_from_path(exe)
|
||||
|
||||
# Figure out the shebang from the resulting command
|
||||
cmd = parse_filename(exe) + (exe,) + cmd[1:]
|
||||
|
||||
# This could have given us back another bare executable
|
||||
exe = normexe(cmd[0])
|
||||
|
||||
return (exe,) + cmd[1:]
|
||||
cmd = (exe,) + cmd[1:]
|
||||
return ShelPathConv.ConvertArgs(*cmd) if convert else cmd
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue