mirror of
https://github.com/outbackdingo/OpCore-Simplify.git
synced 2026-01-27 18:19:49 +00:00
* Refactor OpCore-Simplify to GUI version * New ConfigEditor * Add requirement checks and installation in launchers * Add GitHub Actions workflow to generate manifest.json * Set compression level for asset * Skip .git and __pycache__ folders * Refactor update process to include integrity checker * Add SMBIOS model selection * Update README.md * Update to main branch
163 lines
5.5 KiB
Python
163 lines
5.5 KiB
Python
import os
|
|
import json
|
|
import plistlib
|
|
import shutil
|
|
import re
|
|
import binascii
|
|
import subprocess
|
|
import zipfile
|
|
import tempfile
|
|
import traceback
|
|
import contextlib
|
|
import logging
|
|
|
|
class Utils:
|
|
def __init__(self):
|
|
self.gui_handler = None
|
|
self.logger = logging.getLogger("OpCoreSimplify")
|
|
|
|
@contextlib.contextmanager
|
|
def safe_block(self, task_name="Operation", suppress_error=True):
|
|
try:
|
|
yield
|
|
except Exception as e:
|
|
error_details = "".join(traceback.format_exc())
|
|
self.log_message("Error during '{}': {}\n{}".format(task_name, str(e), error_details), level="ERROR")
|
|
if not suppress_error:
|
|
raise
|
|
|
|
def log_message(self, message, level="INFO", to_build_log=False):
|
|
log_level = getattr(logging, level.upper(), logging.INFO)
|
|
|
|
extra = {'to_build_log': to_build_log}
|
|
|
|
self.logger.log(log_level, message, extra=extra)
|
|
return True
|
|
|
|
def clean_temporary_dir(self):
|
|
temporary_dir = tempfile.gettempdir()
|
|
|
|
for file in os.listdir(temporary_dir):
|
|
if file.startswith("ocs_"):
|
|
|
|
if not os.path.isdir(os.path.join(temporary_dir, file)):
|
|
continue
|
|
|
|
try:
|
|
shutil.rmtree(os.path.join(temporary_dir, file))
|
|
except Exception as e:
|
|
self.log_message("[UTILS] Failed to remove temp directory {}: {}".format(file, e), "Error")
|
|
pass
|
|
|
|
def get_temporary_dir(self):
|
|
return tempfile.mkdtemp(prefix="ocs_")
|
|
|
|
def write_file(self, file_path, data):
|
|
file_extension = os.path.splitext(file_path)[1]
|
|
|
|
with open(file_path, "w" if file_extension == ".json" else "wb") as file:
|
|
if file_extension == ".json":
|
|
json.dump(data, file, indent=4)
|
|
else:
|
|
if file_extension == ".plist":
|
|
data = plistlib.dumps(data)
|
|
|
|
file.write(data)
|
|
|
|
def read_file(self, file_path):
|
|
if not os.path.exists(file_path):
|
|
return None
|
|
|
|
file_extension = os.path.splitext(file_path)[1]
|
|
|
|
with open(file_path, "r" if file_extension == ".json" else "rb") as file_handle:
|
|
if file_extension == ".plist":
|
|
data = plistlib.load(file_handle)
|
|
elif file_extension == ".json":
|
|
data = json.load(file_handle)
|
|
else:
|
|
data = file_handle.read()
|
|
return data
|
|
|
|
def find_matching_paths(self, root_path, extension_filter=None, name_filter=None, type_filter=None):
|
|
|
|
def is_valid_item(name):
|
|
if name.startswith("."):
|
|
return False
|
|
if extension_filter and not name.lower().endswith(extension_filter.lower()):
|
|
return False
|
|
if name_filter and name_filter not in name:
|
|
return False
|
|
return True
|
|
|
|
found_paths = []
|
|
|
|
for root, dirs, files in os.walk(root_path):
|
|
relative_root = root.replace(root_path, "")[1:]
|
|
|
|
if type_filter in (None, "dir"):
|
|
for d in dirs:
|
|
if is_valid_item(d):
|
|
found_paths.append((os.path.join(relative_root, d), "dir"))
|
|
|
|
if type_filter in (None, "file"):
|
|
for file in files:
|
|
if is_valid_item(file):
|
|
found_paths.append((os.path.join(relative_root, file), "file"))
|
|
|
|
return sorted(found_paths, key=lambda path: path[0])
|
|
|
|
def create_folder(self, path, remove_content=False):
|
|
if os.path.exists(path):
|
|
if remove_content:
|
|
shutil.rmtree(path)
|
|
os.makedirs(path)
|
|
else:
|
|
os.makedirs(path)
|
|
|
|
def hex_to_bytes(self, string):
|
|
try:
|
|
hex_string = re.sub(r'[^0-9a-fA-F]', '', string)
|
|
|
|
if len(re.sub(r"\s+", "", string)) != len(hex_string):
|
|
return string
|
|
|
|
return binascii.unhexlify(hex_string)
|
|
except binascii.Error:
|
|
return string
|
|
|
|
def int_to_hex(self, number):
|
|
return format(number, '02X')
|
|
|
|
def to_little_endian_hex(self, hex_string):
|
|
hex_string = hex_string.lower().lstrip("0x")
|
|
|
|
return ''.join(reversed([hex_string[i:i+2] for i in range(0, len(hex_string), 2)])).upper()
|
|
|
|
def string_to_hex(self, string):
|
|
return ''.join(format(ord(char), '02X') for char in string)
|
|
|
|
def extract_zip_file(self, zip_path, extraction_directory=None):
|
|
if extraction_directory is None:
|
|
extraction_directory = os.path.splitext(zip_path)[0]
|
|
|
|
os.makedirs(extraction_directory, exist_ok=True)
|
|
|
|
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
|
|
zip_ref.extractall(extraction_directory)
|
|
|
|
def contains_any(self, data, search_item, start=0, end=None):
|
|
return next((item for item in data[start:end] if item.lower() in search_item.lower()), None)
|
|
|
|
def parse_darwin_version(self, darwin_version):
|
|
major, minor, patch = map(int, darwin_version.split('.'))
|
|
return major, minor, patch
|
|
|
|
def open_folder(self, folder_path):
|
|
if os.name == 'posix':
|
|
if 'darwin' in os.uname().sysname.lower():
|
|
subprocess.run(['open', folder_path])
|
|
else:
|
|
subprocess.run(['xdg-open', folder_path])
|
|
elif os.name == 'nt':
|
|
os.startfile(folder_path) |