psutil

Форк
0
/
git_pre_commit.py 
170 строк · 4.5 Кб
1
#!/usr/bin/env python3
2

3
# Copyright (c) 2009 Giampaolo Rodola'. All rights reserved.
4
# Use of this source code is governed by a BSD-style license that can be
5
# found in the LICENSE file.
6

7
"""This gets executed on 'git commit' and rejects the commit in case
8
the submitted code does not pass validation. Validation is run only
9
against the files which were modified in the commit. Install this with
10
"make install-git-hooks".
11
"""
12

13
from __future__ import print_function
14

15
import os
16
import shlex
17
import subprocess
18
import sys
19

20

21
PYTHON = sys.executable
22
PY3 = sys.version_info[0] >= 3
23
THIS_SCRIPT = os.path.realpath(__file__)
24

25

26
def term_supports_colors():
27
    try:
28
        import curses
29

30
        assert sys.stderr.isatty()
31
        curses.setupterm()
32
        assert curses.tigetnum("colors") > 0
33
    except Exception:  # noqa: BLE001
34
        return False
35
    return True
36

37

38
def hilite(s, ok=True, bold=False):
39
    """Return an highlighted version of 'string'."""
40
    if not term_supports_colors():
41
        return s
42
    attr = []
43
    if ok is None:  # no color
44
        pass
45
    elif ok:  # green
46
        attr.append('32')
47
    else:  # red
48
        attr.append('31')
49
    if bold:
50
        attr.append('1')
51
    return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), s)
52

53

54
def exit(msg):
55
    print(hilite("commit aborted: " + msg, ok=False), file=sys.stderr)
56
    sys.exit(1)
57

58

59
def sh(cmd):
60
    if isinstance(cmd, str):
61
        cmd = shlex.split(cmd)
62
    p = subprocess.Popen(
63
        cmd,
64
        stdout=subprocess.PIPE,
65
        stderr=subprocess.PIPE,
66
        universal_newlines=True,
67
    )
68
    stdout, stderr = p.communicate()
69
    if p.returncode != 0:
70
        raise RuntimeError(stderr)
71
    if stderr:
72
        print(stderr, file=sys.stderr)
73
    if stdout.endswith('\n'):
74
        stdout = stdout[:-1]
75
    return stdout
76

77

78
def open_text(path):
79
    kw = {'encoding': 'utf8'} if PY3 else {}
80
    return open(path, **kw)
81

82

83
def git_commit_files():
84
    out = sh(["git", "diff", "--cached", "--name-only"])
85
    py_files = [
86
        x for x in out.split('\n') if x.endswith('.py') and os.path.exists(x)
87
    ]
88
    c_files = [
89
        x
90
        for x in out.split('\n')
91
        if x.endswith(('.c', '.h')) and os.path.exists(x)
92
    ]
93
    rst_files = [
94
        x for x in out.split('\n') if x.endswith('.rst') and os.path.exists(x)
95
    ]
96
    toml_files = [
97
        x for x in out.split("\n") if x.endswith(".toml") and os.path.exists(x)
98
    ]
99
    new_rm_mv = sh(
100
        ["git", "diff", "--name-only", "--diff-filter=ADR", "--cached"]
101
    )
102
    # XXX: we should escape spaces and possibly other amenities here
103
    new_rm_mv = new_rm_mv.split()
104
    return (py_files, c_files, rst_files, toml_files, new_rm_mv)
105

106

107
def black(files):
108
    print("running black (%s)" % len(files))
109
    cmd = [PYTHON, "-m", "black", "--check", "--safe"] + files
110
    if subprocess.call(cmd) != 0:
111
        return exit(
112
            "Python code didn't pass 'ruff' style check."
113
            "Try running 'make fix-ruff'."
114
        )
115

116

117
def ruff(files):
118
    print("running ruff (%s)" % len(files))
119
    cmd = [PYTHON, "-m", "ruff", "check", "--no-cache"] + files
120
    if subprocess.call(cmd) != 0:
121
        return exit(
122
            "Python code didn't pass 'ruff' style check."
123
            "Try running 'make fix-ruff'."
124
        )
125

126

127
def c_linter(files):
128
    print("running clinter (%s)" % len(files))
129
    # XXX: we should escape spaces and possibly other amenities here
130
    cmd = [PYTHON, "scripts/internal/clinter.py"] + files
131
    if subprocess.call(cmd) != 0:
132
        return sys.exit("C code didn't pass style check")
133

134

135
def toml_sort(files):
136
    print("running toml linter (%s)" % len(files))
137
    cmd = ["toml-sort", "--check"] + files
138
    if subprocess.call(cmd) != 0:
139
        return sys.exit("%s didn't pass style check" % ' '.join(files))
140

141

142
def rstcheck(files):
143
    print("running rst linter (%s)" % len(files))
144
    cmd = ["rstcheck", "--config=pyproject.toml"] + files
145
    if subprocess.call(cmd) != 0:
146
        return sys.exit("RST code didn't pass style check")
147

148

149
def main():
150
    py_files, c_files, rst_files, toml_files, new_rm_mv = git_commit_files()
151
    if py_files:
152
        black(py_files)
153
        ruff(py_files)
154
    if c_files:
155
        c_linter(c_files)
156
    if rst_files:
157
        rstcheck(rst_files)
158
    if toml_files:
159
        toml_sort(toml_files)
160
    if new_rm_mv:
161
        out = sh([PYTHON, "scripts/internal/generate_manifest.py"])
162
        with open_text('MANIFEST.in') as f:
163
            if out.strip() != f.read().strip():
164
                sys.exit(
165
                    "some files were added, deleted or renamed; "
166
                    "run 'make generate-manifest' and commit again"
167
                )
168

169

170
main()
171

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.