added get_hash_map and comp_dict_changes to get information about all the files of an extracted game

This commit is contained in:
Faraphel 2022-08-27 00:28:15 +02:00
parent b9d6913e22
commit 9f8aa05c04
7 changed files with 72 additions and 33 deletions

View file

@ -1,9 +1,3 @@
import os
import sys
from threading import Thread
from typing import Callable
# metadata
__version__ = (0, 12, 0)
__author__ = 'Faraphel'
@ -21,33 +15,10 @@ Mo: int = 1_000 * Ko
Go: int = 1_000 * Mo
minimum_space_available: int = 15*Go
file_block_size: int = 128*Ko
# global type hint
TemplateSafeEval: str
TemplateMultipleSafeEval: str
Env: dict[str, any]
# useful functions
def threaded(func: Callable) -> Callable:
"""
Decorate a function to run in a separate thread
:param func: a function
:return: the decorated function
"""
def wrapper(*args, **kwargs):
# run the function in a Daemon, so it will stop when the main thread stops
thread = Thread(target=func, args=args, kwargs=kwargs, daemon=True)
thread.start()
return thread
return wrapper
def restart_program():
"""
Restart the program
"""
os.execl(sys.executable, sys.executable, *sys.argv)

View file

@ -17,6 +17,7 @@ from source.progress import Progress
from source.translation import translate as _, translate_external
from source import plugins
from source import *
from source.utils import threaded
import os
from source.mkw.collection.Extension import Extension

View file

@ -1,8 +1,10 @@
import hashlib
import shutil
from io import BytesIO
from pathlib import Path
from typing import Generator, IO, TYPE_CHECKING
from source import file_block_size
from source.mkw.ModConfig import ModConfig
from source.mkw.Patch.Patch import Patch
from source.mkw.collection.Extension import Extension
@ -202,3 +204,20 @@ class ExtractedGame:
shutil.rmtree(self.path)
return converted_game
def get_hash_map(self) -> dict[str, str]:
"""
Return a dictionary associating all the game subfiles to a hash
:return: a dictionary associating all the game subfiles to a hash
"""
md5_map: dict[str, str] = {}
for fp in filter(lambda fp: fp.is_file(), self.path.rglob("*")):
hasher = hashlib.md5()
with open(fp, "rb") as file:
while block := file.read(file_block_size):
hasher.update(block)
md5_map[str(fp.relative_to(self.path))] = hasher.hexdigest()
return md5_map

View file

@ -7,6 +7,7 @@ from source.mkw.collection.Extension import Extension
from source.mkw.collection.Region import Region
from source.option import Options
from source.progress import Progress
from source.utils import comp_dict_changes
from source.wt.wit import WITPath
from source.translation import translate as _
@ -123,6 +124,9 @@ class Game:
yield Progress(title=_("EXTRACTION"), set_part=1)
yield from self.extract(extracted_game.path)
# Riivolution hash map for the final comparaison
riivolution_original_hash_map = extracted_game.get_hash_map()
# install mystuff
yield Progress(title=_("MYSTUFF"), set_part=2)
mystuff_packs = options.mystuff_packs.get()
@ -158,7 +162,15 @@ class Game:
yield from extracted_game.install_all_patch(mod_config)
yield from extracted_game.recreate_all_szs()
# Riivolution comparaison
riivolution_patched_hash_map = extracted_game.get_hash_map()
riivolution_diff: dict[str, Path] = comp_dict_changes(
riivolution_original_hash_map,
riivolution_patched_hash_map
)
# convert the extracted game into a file
yield Progress(title=_("CONVERTING_TO_GAME_FILE"), set_part=7)
converted_game: WITPath = yield from extracted_game.convert_to(output_type)
if converted_game is not None: yield from Game(converted_game.path).edit(mod_config)

View file

@ -1,11 +1,11 @@
import shutil
from dataclasses import dataclass, field
from pathlib import Path
from typing import Generator, Callable, Iterator, Iterable, TYPE_CHECKING
from typing import Generator, Callable, Iterator, TYPE_CHECKING
import json
from PIL import Image
from source import threaded
from source.utils import threaded
from source.mkw import Tag
from source.mkw.ModSettings.ModSettingsGroup import ModSettingsGroup
from source.mkw.Track.Cup import Cup

View file

@ -1,7 +1,7 @@
import json
from pathlib import Path
from source import restart_program
from source.utils import restart_program
class OptionLoadingError(Exception):

36
source/utils.py Normal file
View file

@ -0,0 +1,36 @@
import os
import sys
from threading import Thread
from typing import Callable
# useful functions
def threaded(func: Callable) -> Callable:
"""
Decorate a function to run in a separate thread
:param func: a function
:return: the decorated function
"""
def wrapper(*args, **kwargs):
# run the function in a Daemon, so it will stop when the main thread stops
thread = Thread(target=func, args=args, kwargs=kwargs, daemon=True)
thread.start()
return thread
return wrapper
def restart_program():
"""
Restart the program
"""
os.execl(sys.executable, sys.executable, *sys.argv)
def comp_dict_changes(d_old: dict, d_new: dict) -> dict:
"""
Return a comparaison dict showing every value that changed between d_old and d_new. Deleted value are ignored.
Example : {"a": 1, "b": 3, "d": 13}, {"b": 2, "c": 10, "d": 13} -> {"b": 2, "c": 10}
"""
return {name: value for name, value in d_new.items() if d_old.get(name) != value}