mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-30 13:13:00 +00:00 
			
		
		
		
	 367773e173
			
		
	
	367773e173
	
	
	
		
			
			- Separate FileMount into separate FileMount and WritableFileMount classes. This separates the (relatively simple) read-only code from the (soon to be even more complex) read/write code. It also allows you to create read-only mounts which don't bother with filesystem accounting, which is nice. - Make openForWrite/openForAppend always return a SeekableFileHandle. Appendable files still cannot be seeked within, but that check is now done on the FS side. - Refactor the various mount tests to live in test contract interfaces, allowing us to reuse them between mounts. - Clean up our error handling a little better. (Most) file-specific code has been moved to FileMount, and ArchiveMount-derived classes now throw correct path-localised exceptions.
		
			
				
	
	
		
			149 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env python3
 | |
| """
 | |
| Parse reports generated by Gradle and convert them into GitHub annotations.
 | |
| 
 | |
| See https://github.com/actions/toolkit/blob/master/docs/problem-matchers.md and
 | |
| https://github.com/actions/toolkit/blob/master/docs/commands.md.
 | |
| """
 | |
| 
 | |
| import os.path
 | |
| import pathlib
 | |
| import re
 | |
| import xml.etree.ElementTree as ET
 | |
| from typing import Optional, Tuple
 | |
| 
 | |
| LUA_ERROR_LOCATION = re.compile(r"^\s+(/[\w./-]+):(\d+):", re.MULTILINE)
 | |
| JAVA_LUA_ERROR_LOCATION = re.compile(r"^java.lang.IllegalStateException: (/[\w./-]+):(\d+):")
 | |
| JAVA_ERROR_LOCATION = re.compile(r"^\tat ([\w.]+)\.[\w]+\([\w.]+:(\d+)\)$", re.MULTILINE)
 | |
| ERROR_MESSAGE = re.compile(r"(.*)\nstack traceback:", re.DOTALL)
 | |
| 
 | |
| SPACES = re.compile(r"\s+")
 | |
| 
 | |
| SOURCE_LOCATIONS = [
 | |
|     "src/main/java",
 | |
|     "src/main/resources/data/computercraft/lua",
 | |
|     "src/test/java",
 | |
|     "src/test/resources",
 | |
| ]
 | |
| 
 | |
| PROJECT_LOCATIONS = [
 | |
|     "projects/core-api",
 | |
|     "projects/core",
 | |
|     "projects/common-api",
 | |
|     "projects/common",
 | |
|     "projects/fabric-api",
 | |
|     "projects/fabric",
 | |
|     "projects/forge-api",
 | |
|     "projects/forge",
 | |
| ]
 | |
| 
 | |
| TEST_REPORTS = []
 | |
| 
 | |
| 
 | |
| def find_file(path: str) -> Optional[str]:
 | |
|     while len(path) > 0 and path[0] == "/":
 | |
|         path = path[1:]
 | |
| 
 | |
|     for project in PROJECT_LOCATIONS:
 | |
|         for source_dir in SOURCE_LOCATIONS:
 | |
|             child_path = os.path.join(project, source_dir, path)
 | |
|             if os.path.exists(child_path):
 | |
|                 return child_path
 | |
| 
 | |
|     return None
 | |
| 
 | |
| 
 | |
| def find_location(message: str) -> Optional[Tuple[str, str]]:
 | |
|     location = LUA_ERROR_LOCATION.search(message)
 | |
|     if location:
 | |
|         file = find_file(location[1])
 | |
|         if file:
 | |
|             return file, location[2]
 | |
| 
 | |
|     location = JAVA_LUA_ERROR_LOCATION.search(message)
 | |
|     if location:
 | |
|         file = find_file(location[1])
 | |
|         if file:
 | |
|             return file, location[2]
 | |
| 
 | |
|     for location in JAVA_ERROR_LOCATION.findall(message):
 | |
|         file = find_file(location[0].replace(".", "/") + ".java")
 | |
|         if file:
 | |
|             return file, location[1]
 | |
| 
 | |
|     return None
 | |
| 
 | |
| 
 | |
| def _parse_junit_file(path: pathlib.Path):
 | |
|     for testcase in ET.parse(path).findall(".//testcase"):
 | |
|         for result in testcase:
 | |
|             if result.tag == "skipped":
 | |
|                 continue
 | |
| 
 | |
|             name = f'{testcase.attrib["classname"]}.{testcase.attrib["name"]}'
 | |
|             message = result.attrib.get("message")
 | |
|             full_message = result.text or message
 | |
| 
 | |
|             location = find_location(full_message)
 | |
|             error = ERROR_MESSAGE.match(message)
 | |
|             if error:
 | |
|                 error = error[1]
 | |
|             else:
 | |
|                 error = message
 | |
| 
 | |
|             if location:
 | |
|                 print(f'## {location[0]}:{location[1]}: {name} failed: {SPACES.sub(" ", error)}')
 | |
|             else:
 | |
|                 print(f"::error::{name} failed")
 | |
| 
 | |
|             print("::group::Full error message")
 | |
|             print(full_message)
 | |
|             print("::endgroup::")
 | |
| 
 | |
| 
 | |
| def parse_junit() -> None:
 | |
|     """
 | |
|     Scrape JUnit test reports for errors. We determine the location from the Lua
 | |
|     or Java stacktrace.
 | |
|     """
 | |
|     print("::add-matcher::.github/matchers/junit.json")
 | |
| 
 | |
|     for project in PROJECT_LOCATIONS:
 | |
|         for path in pathlib.Path(os.path.join(project, "build/test-results/test")).glob("TEST-*.xml"):
 | |
|             _parse_junit_file(path)
 | |
| 
 | |
|         for path in pathlib.Path(os.path.join(project, "build/test-results")).glob("run*.xml"):
 | |
|             _parse_junit_file(path)
 | |
| 
 | |
|     print("::remove-matcher owner=junit::")
 | |
| 
 | |
| 
 | |
| def _parse_checkstyle(path: pathlib.Path):
 | |
|     for file in ET.parse(path).getroot():
 | |
|         for error in file:
 | |
|             filename = os.path.relpath(file.attrib["name"])
 | |
| 
 | |
|             attrib = error.attrib
 | |
|             print(
 | |
|                 f'{attrib["severity"]} {filename}:{attrib["line"]}:{attrib.get("column", 1)}: {SPACES.sub(" ", attrib["message"])}'
 | |
|             )
 | |
| 
 | |
| 
 | |
| def parse_checkstyle() -> None:
 | |
|     """
 | |
|     Scrape JUnit test reports for errors. We determine the location from the Lua
 | |
|     or Java stacktrace.
 | |
|     """
 | |
|     print("::add-matcher::.github/matchers/checkstyle.json")
 | |
| 
 | |
|     for project in PROJECT_LOCATIONS:
 | |
|         for path in pathlib.Path(os.path.join(project, "build/reports/checkstyle/")).glob("*.xml"):
 | |
|             _parse_checkstyle(path)
 | |
| 
 | |
|     print("::remove-matcher owner=checkstyle::")
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     parse_junit()
 | |
|     parse_checkstyle()
 |