1#!/usr/bin/env python3
2
3# Copyright 2012-2019 The Meson development team
4
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8
9#     http://www.apache.org/licenses/LICENSE-2.0
10
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# some simple checks on the file format of:
18# - python code
19# - code samples in tests
20# - markdown documentation
21#
22# checks are:
23# - no use of tabs
24# - no use of DOS line endings
25
26import os
27import re
28from pathlib import Path
29
30def check_file(file: Path) -> None:
31    lines = file.read_bytes().split(b'\n')
32    tabdetector = re.compile(br' *\t')
33    for i, line in enumerate(lines):
34        if re.match(tabdetector, line):
35            raise SystemExit("File {} contains a tab indent on line {:d}. Only spaces are permitted.".format(file, i + 1))
36        if line.endswith(b'\r'):
37            raise SystemExit("File {} contains DOS line ending on line {:d}. Only unix-style line endings are permitted.".format(file, i + 1))
38
39def check_format() -> None:
40    check_suffixes = {'.c',
41                      '.cpp',
42                      '.cxx',
43                      '.cc',
44                      '.rs',
45                      '.f90',
46                      '.vala',
47                      '.d',
48                      '.s',
49                      '.m',
50                      '.mm',
51                      '.asm',
52                      '.java',
53                      '.txt',
54                      '.py',
55                      '.swift',
56                      '.build',
57                      '.md',
58                      }
59    skip_dirs = {
60        '.dub',                         # external deps are here
61        '.pytest_cache',
62        'meson-logs', 'meson-private',
63        'work area',
64        '.eggs', '_cache',              # e.g. .mypy_cache
65        'venv',                         # virtualenvs have DOS line endings
66    }
67    for (root, _, filenames) in os.walk('.'):
68        if any([x in root for x in skip_dirs]):
69            continue
70        for fname in filenames:
71            file = Path(fname)
72            if file.suffix.lower() in check_suffixes:
73                if file.name in ('sitemap.txt', 'meson-test-run.txt'):
74                    continue
75                check_file(root / file)
76
77
78if __name__ == '__main__':
79    script_dir = os.path.split(__file__)[0]
80    if script_dir != '':
81        os.chdir(script_dir)
82    check_format()
83