151 lines
5.4 KiB
Python
151 lines
5.4 KiB
Python
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")
|