import glob import hashlib import json import shutil import subprocess from .patchers import patch_core_build from .patchers import patch_metadata from .config import * product_name = "None" # Читается из metadata icon = "" # Читается из metadata splash = "" # Читается из metadata def get_pyinstaller_cmd(): splash_str = "" uac_admin = "" dwt = "" windows_mode = "--console" if windowed[0]: windows_mode = "-w" add_data = [f'--add-data {path_fix + d}' for d in data] if splash: splash_str = f' --splash {path_fix + splash} ' if add_data: add_data = f" {' '.join(add_data)}" if disable_windowed_traceback: dwt = " --disable-windowed-traceback " if admin: uac_admin = " --uac-admin " pyinstaller_cmd = \ (f'pyinstaller --noconfirm --onedir {windows_mode} --clean ' f'--icon {path_fix + icon} --version-file {path_fix + metadata_path_txt}' f'{splash_str}{add_data}{dwt}{uac_admin}' f'--workpath {workpath} --distpath {distpath} --specpath {specpath} ' f'--contents-directory {contents_directory} --optimize {optimize} ' f'--name {product_name} {main}').split(" ") pyinstaller_cmd = [x for x in pyinstaller_cmd if x] logger.info(f"execute: {pyinstaller_cmd}") return pyinstaller_cmd def calculate_sha256(file_path): sha256_hash = hashlib.sha256() with open(file_path, "rb") as f: for byte_block in iter(lambda: f.read(4096), b""): sha256_hash.update(byte_block) return sha256_hash.hexdigest() # Функция для получения списка файлов с их хешами def generate_file_list_with_sha256(directory): file_list = {} for root, dirs, files in os.walk(directory): for file in files: file_path = os.path.join(root, file) file_sha256 = calculate_sha256(file_path) file_list[file_path] = (file_sha256, os.path.getsize(file_path)) return file_list # Функция для нахождения различий def find_differences(old, new): diff = {} # Найдем файлы, которые есть в одном списке, но не в другом for file_path, (sha256, size) in old.items(): if file_path not in new: diff[file_path] = ('deleted', sha256) elif sha256 != new[file_path][0]: diff[file_path] = ('updated', sha256) for file_path, (sha256, size) in new.items(): if file_path not in old: diff[file_path] = ('new_file', sha256) return diff def save_sha256(file_list, path:str=sha_file): with open(path, 'w') as file: # noinspection PyTypeChecker json.dump(file_list, file, indent=4) def read_sha256(): with open(sha_file, 'r') as file: return json.load(file) def prepare_dist(): for f in glob.glob(os.path.join(distpath, "warn*.txt")): os.remove(f) new_shas = generate_file_list_with_sha256(distpath) if not sha_file.exists(): save_sha256(new_shas) return new_shas def generate_patch(old_ver, new_ver, diff): update_dir = patch_dir.format(old_ver=old_ver, new_ver=new_ver) os.makedirs(update_dir, exist_ok=True) for file_path, (status, _) in diff.copy().items(): rel_path = os.path.relpath(file_path, distpath + product_name) # Убираем лишнюю часть пути del diff[file_path] # Удаляем из списка файлов diff.update({rel_path: status}) # Добавляем новый путь if status == 'deleted': continue target_path = os.path.join(update_dir, rel_path) # Куда копировать os.makedirs(os.path.dirname(target_path), exist_ok=True) # Создаем папку, если её нет shutil.copy(file_path, target_path) save_sha256(diff, patch_file.format(old_ver=old_ver, new_ver=new_ver)) return update_dir def zip_latest(version): shutil.make_archive(f"{dist_dir}/{product_name}-{version}", 'zip', latest_dir) def update_latest(): shutil.rmtree(latest_dir) shutil.copytree(distpath + product_name, latest_dir) def cleanup(): shutil.rmtree(build_dir) os.makedirs(build_dir, exist_ok=True) def build(): global product_name, icon, splash new_ver = patch_core_build() old_ver, product_name, icon, splash = patch_metadata(*new_ver) logger.info("Building...") # subprocess.run(['auto-py-to-exe', '--config', build_json_path], shell=True) subprocess.run(get_pyinstaller_cmd()) if not os.path.exists(distpath): logger.info("[ERR] Build unsuccessful") return logger.info("Build successful") logger.info("Preparing dist") logger.info(" - generating sha256") new_sha = prepare_dist() old_sha = read_sha256() logger.info(" - comparing..") diff = find_differences(old_sha, new_sha) logger.info(f" - {len(diff)} differences found") new_ver = f"{new_ver[0]}.{new_ver[1]}.{new_ver[2]}.{new_ver[3]}" if diff: update_dir = generate_patch(old_ver, new_ver, diff) logger.info(f" - diffs in: {update_dir.split('/')[-1]}") logger.info(" - saving..") save_sha256(new_sha) update_latest() zip_latest(new_ver) logger.info(" - cleaning up") cleanup() logger.info("Ready") shutil.copy(log_file, log_dir / f"build_{new_ver}.log")