|
2 | 2 | PROJECT: ReactOS rapps-db validator
|
3 | 3 | LICENSE: MIT (https://spdx.org/licenses/MIT)
|
4 | 4 | PURPOSE: Validate all rapps-db files
|
5 |
| -COPYRIGHT: Copyright 2020-2023 Mark Jansen <[email protected]> |
| 5 | +COPYRIGHT: Copyright 2020-2024 Mark Jansen <[email protected]> |
6 | 6 | '''
|
7 |
| -import os |
| 7 | +from pathlib import Path |
8 | 8 | import sys
|
9 | 9 | from enum import Enum, unique
|
| 10 | +import struct; |
| 11 | + |
10 | 12 |
|
11 | 13 | # TODO: make this even nicer by using https://github.com/pytorch/add-annotations-github-action
|
12 | 14 |
|
13 |
| -REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| 15 | +REPO_ROOT = Path(__file__).parents[1] |
14 | 16 |
|
15 | 17 | REQUIRED_SECTION_KEYS = [
|
16 | 18 | b'Name',
|
@@ -95,6 +97,10 @@ def add(self, line, column, problem):
|
95 | 97 | idx = column - 1 + len("b'") # Offset the b' prefix
|
96 | 98 | print(' ' * idx + '^')
|
97 | 99 |
|
| 100 | + def add_file(self, file, problem): |
| 101 | + self._problems += 1 |
| 102 | + print('{file}: {problem}'.format(file=file, problem=problem)) |
| 103 | + |
98 | 104 | def problems(self):
|
99 | 105 | return self._problems > 0
|
100 | 106 |
|
@@ -227,11 +233,11 @@ def text(self):
|
227 | 233 | class RappsFile:
|
228 | 234 | def __init__(self, fullname):
|
229 | 235 | self.path = fullname
|
230 |
| - self.filename = os.path.basename(fullname) |
| 236 | + self.filename = fullname.name |
231 | 237 | self._sections = []
|
232 | 238 |
|
233 | 239 | def parse(self, reporter):
|
234 |
| - with open(self.path, 'rb') as f: |
| 240 | + with open(str(self.path), 'rb') as f: |
235 | 241 | lines = [RappsLine(self, idx + 1, line) for idx, line in enumerate(f.readlines())]
|
236 | 242 |
|
237 | 243 | # Create sections from all lines, and add keyvalue entries in their own section
|
@@ -298,14 +304,38 @@ def verify_unique(reporter, lines, line, name):
|
298 | 304 | else:
|
299 | 305 | lines[name] = line
|
300 | 306 |
|
301 |
| - |
302 |
| -def validate_repo(dirname): |
| 307 | +def validate_single_icon(icon, reporter): |
| 308 | + try: |
| 309 | + with open(icon, 'rb') as f: |
| 310 | + header = f.read(4) |
| 311 | + # First we validate the header |
| 312 | + if header != b'\x00\x00\x01\x00': |
| 313 | + reporter.add_file('icons/' + icon.name, 'Bad icon header') |
| 314 | + return |
| 315 | + # Check that there is at least one icon |
| 316 | + num_icons, = struct.unpack('<H', f.read(2)) |
| 317 | + if num_icons == 0: |
| 318 | + reporter.add_file('icons/' + icon.name, 'Empty icon?') |
| 319 | + return |
| 320 | + # Should we validate / display individual icons? |
| 321 | + # See https://en.wikipedia.org/wiki/ICO_(file_format)#Structure_of_image_directory |
| 322 | + except Exception as e: |
| 323 | + reporter.add_file('icons/' + icon.name, 'Exception while reading icon: ' + str(e)) |
| 324 | + |
| 325 | +def validate_icons(ico_dir, reporter): |
| 326 | + for icon in ico_dir.glob('*.ico'): |
| 327 | + validate_single_icon(icon, reporter) |
| 328 | + |
| 329 | + |
| 330 | +def validate_repo(check_dir): |
303 | 331 | reporter = Reporter()
|
304 | 332 |
|
305 |
| - all_files = [RappsFile(filename) for filename in os.listdir(dirname) if filename.endswith('.txt')] |
| 333 | + all_files = [RappsFile(file) for file in check_dir.glob('*.txt')] |
306 | 334 | for entry in all_files:
|
307 | 335 | entry.parse(reporter)
|
308 | 336 |
|
| 337 | + validate_icons(check_dir / 'icons', reporter) |
| 338 | + |
309 | 339 | if reporter.problems():
|
310 | 340 | print('Please check https://reactos.org/wiki/RAPPS for details on the file format.')
|
311 | 341 | sys.exit(1)
|
|
0 commit comments