mirror of
https://github.com/Faraphel/Atlas-Install.git
synced 2025-07-03 03:08:29 +02:00
added get_hash_map and comp_dict_changes to get information about all the files of an extracted game
This commit is contained in:
parent
b9d6913e22
commit
9f8aa05c04
7 changed files with 72 additions and 33 deletions
|
@ -1,9 +1,3 @@
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from threading import Thread
|
|
||||||
from typing import Callable
|
|
||||||
|
|
||||||
|
|
||||||
# metadata
|
# metadata
|
||||||
__version__ = (0, 12, 0)
|
__version__ = (0, 12, 0)
|
||||||
__author__ = 'Faraphel'
|
__author__ = 'Faraphel'
|
||||||
|
@ -21,33 +15,10 @@ Mo: int = 1_000 * Ko
|
||||||
Go: int = 1_000 * Mo
|
Go: int = 1_000 * Mo
|
||||||
|
|
||||||
minimum_space_available: int = 15*Go
|
minimum_space_available: int = 15*Go
|
||||||
|
file_block_size: int = 128*Ko
|
||||||
|
|
||||||
|
|
||||||
# global type hint
|
# global type hint
|
||||||
TemplateSafeEval: str
|
TemplateSafeEval: str
|
||||||
TemplateMultipleSafeEval: str
|
TemplateMultipleSafeEval: str
|
||||||
Env: dict[str, any]
|
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)
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ from source.progress import Progress
|
||||||
from source.translation import translate as _, translate_external
|
from source.translation import translate as _, translate_external
|
||||||
from source import plugins
|
from source import plugins
|
||||||
from source import *
|
from source import *
|
||||||
|
from source.utils import threaded
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from source.mkw.collection.Extension import Extension
|
from source.mkw.collection.Extension import Extension
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
import hashlib
|
||||||
import shutil
|
import shutil
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Generator, IO, TYPE_CHECKING
|
from typing import Generator, IO, TYPE_CHECKING
|
||||||
|
|
||||||
|
from source import file_block_size
|
||||||
from source.mkw.ModConfig import ModConfig
|
from source.mkw.ModConfig import ModConfig
|
||||||
from source.mkw.Patch.Patch import Patch
|
from source.mkw.Patch.Patch import Patch
|
||||||
from source.mkw.collection.Extension import Extension
|
from source.mkw.collection.Extension import Extension
|
||||||
|
@ -202,3 +204,20 @@ class ExtractedGame:
|
||||||
shutil.rmtree(self.path)
|
shutil.rmtree(self.path)
|
||||||
|
|
||||||
return converted_game
|
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
|
||||||
|
|
|
@ -7,6 +7,7 @@ from source.mkw.collection.Extension import Extension
|
||||||
from source.mkw.collection.Region import Region
|
from source.mkw.collection.Region import Region
|
||||||
from source.option import Options
|
from source.option import Options
|
||||||
from source.progress import Progress
|
from source.progress import Progress
|
||||||
|
from source.utils import comp_dict_changes
|
||||||
from source.wt.wit import WITPath
|
from source.wt.wit import WITPath
|
||||||
from source.translation import translate as _
|
from source.translation import translate as _
|
||||||
|
|
||||||
|
@ -123,6 +124,9 @@ class Game:
|
||||||
yield Progress(title=_("EXTRACTION"), set_part=1)
|
yield Progress(title=_("EXTRACTION"), set_part=1)
|
||||||
yield from self.extract(extracted_game.path)
|
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
|
# install mystuff
|
||||||
yield Progress(title=_("MYSTUFF"), set_part=2)
|
yield Progress(title=_("MYSTUFF"), set_part=2)
|
||||||
mystuff_packs = options.mystuff_packs.get()
|
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.install_all_patch(mod_config)
|
||||||
yield from extracted_game.recreate_all_szs()
|
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
|
# convert the extracted game into a file
|
||||||
yield Progress(title=_("CONVERTING_TO_GAME_FILE"), set_part=7)
|
yield Progress(title=_("CONVERTING_TO_GAME_FILE"), set_part=7)
|
||||||
converted_game: WITPath = yield from extracted_game.convert_to(output_type)
|
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)
|
if converted_game is not None: yield from Game(converted_game.path).edit(mod_config)
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import shutil
|
import shutil
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Generator, Callable, Iterator, Iterable, TYPE_CHECKING
|
from typing import Generator, Callable, Iterator, TYPE_CHECKING
|
||||||
import json
|
import json
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
from source import threaded
|
from source.utils import threaded
|
||||||
from source.mkw import Tag
|
from source.mkw import Tag
|
||||||
from source.mkw.ModSettings.ModSettingsGroup import ModSettingsGroup
|
from source.mkw.ModSettings.ModSettingsGroup import ModSettingsGroup
|
||||||
from source.mkw.Track.Cup import Cup
|
from source.mkw.Track.Cup import Cup
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from source import restart_program
|
from source.utils import restart_program
|
||||||
|
|
||||||
|
|
||||||
class OptionLoadingError(Exception):
|
class OptionLoadingError(Exception):
|
||||||
|
|
36
source/utils.py
Normal file
36
source/utils.py
Normal 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}
|
Loading…
Reference in a new issue