Skip to content

Commit

Permalink
Change YAML parsing methodology and fix some parsing bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
jose-l-martins committed Dec 5, 2024
1 parent 74e5b30 commit e59cfca
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 57 deletions.
43 changes: 33 additions & 10 deletions file_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from special_path_resolver import resolve_special_path
import shutil


def compute_sha1(data_or_file: Union[bytes, str]) -> str:
sha1 = hashlib.sha1()

Expand Down Expand Up @@ -56,7 +57,7 @@ def extract_and_check_files_in_gsba(gsm_gsba_file_path: str, inner_folder_path:
'hash': sha1_hash,
'size': uncompressed_size
}

#Create and copy the the file to the output folder (subfolder 'Temp')
dir_path = os.path.dirname(os.path.join(output_folder_path, "Temp", inner_folder_path, file_path[2:].replace("/", "\\")).replace("\\\\", "\\").replace("/","\\"))
os.makedirs(dir_path, exist_ok=True)
Expand All @@ -82,7 +83,18 @@ def extract_and_check_files_in_gsba(gsm_gsba_file_path: str, inner_folder_path:
'size': uncompressed_size
}
#Create and copy the the file to the output folder (subfolder 'Temp')
dir_path = os.path.dirname(os.path.join(output_folder_path, "Temp", inner_folder_path, file_path[2:].replace("/", "\\")).replace("\\\\", "\\").replace("/","\\"))
inner_folder_path = inner_folder_path.replace("\\", "")
inner_folder_path = inner_folder_path.replace("/", "")

partial_path_1 = os.path.join(output_folder_path, "Temp")
partial_path_1 = os.path.join(partial_path_1, inner_folder_path)
partial_path_2 = file_path[2:]
partial_path_2 = partial_path_2.replace("/", "\\")
partial_path_2 = partial_path_2.replace("\\\\", "\\")
partial_path_2 = partial_path_2.replace("/","\\")
partial_path_2 = (partial_path_2.lstrip("\\")).rstrip("\\")
dir_path = os.path.dirname(os.path.join(partial_path_1, partial_path_2))
#dir_path = os.path.dirname(os.path.join(output_folder_path, "Temp", inner_folder_path, ((file_path[2:].replace("/", "\\")).replace("\\\\", "\\")).replace("/","\\")))
os.makedirs(dir_path, exist_ok=True)
file_to_create = os.path.join(dir_path, os.path.basename(file_path).replace("\\\\", "\\"))
with open(file_to_create, "wb") as file:
Expand All @@ -96,13 +108,24 @@ def extract_and_check_files_in_gsba(gsm_gsba_file_path: str, inner_folder_path:

return results

def move_files_to_gsba_based_on_gsm_xml(inner_folder_path: str, xml_string: str, specific_output_folder_path: str, date_string: str):
def move_files_to_gsba_based_on_gsm_xml(inner_folder_path: str, xml_string: str, specific_output_folder_path: str, date_string: str, inner_folder_name: str):

xml_data = minidom.parseString(xml_string)
game_name = xml_data.getElementsByTagName('GameName')[0].firstChild.data
#Fix game name bad character encoding
game_name = game_name.replace(":","").replace('â„¢', '™').replace('™', '™').replace('®', '®')

archive_name = specific_output_folder_path
output_zip_path = specific_output_folder_path

# Create specific folder, with timestamp, to avoid conflict with files from backups from the same game
# Define the directory and output file paths
#output_zip_path = os.path.join(specific_output_folder_path, f"{game_name}")
# Create the zip file
#archive_name = os.path.dirname(output_zip_path) + "_" + date_string[0:19].replace("T","_").replace(":",".")
#specific_output_folder_path = archive_name


directory_elements = xml_data.getElementsByTagName('Directory')
inner_gsba_folder_i = 1
#dedups_dirs = []
Expand Down Expand Up @@ -134,24 +157,24 @@ def move_files_to_gsba_based_on_gsm_xml(inner_folder_path: str, xml_string: str,
virtual_fullpath = virtual_fullpath.replace("\\", "/")
intermediate_path = inner_folder_path + os.path.sep + game_name
#List folders inside the intermediate path folder
inner_folders = os.listdir(intermediate_path)
#inner_folders = os.listdir(intermediate_path)
#fullpath = inner_folder_path + os.path.sep + game_name + os.path.sep + inner_folders[0] + os.path.sep + virtual_fullpath

fullpath = inner_folder_path + os.path.sep + game_name + os.path.sep + inner_folders[0] + os.path.sep + virtual_fullpath
fullpath = inner_folder_path + os.path.sep + game_name + os.path.sep + inner_folder_name + os.path.sep + virtual_fullpath
fullpath = fullpath.replace("\\", "/")
#Copy file over from 'fullpath' to specific_output_folder_path
dest_folder = os.path.join(specific_output_folder_path, str(inner_gsba_folder_i), os.path.dirname(file_element.firstChild.data))
os.makedirs(dest_folder, exist_ok=True)

shutil.copy(fullpath.replace("\\", "/").replace("////", "/"), os.path.join(dest_folder, os.path.basename(fullpath)))

inner_gsba_folder_i += 1
#dedups_dirs.append(dir_element.getElementsByTagName('Path')[0].firstChild.data)

# Define the directory and output file paths
output_zip_path = os.path.join(specific_output_folder_path, f"{game_name}")
#output_zip_path = os.path.join(specific_output_folder_path, f"{game_name}")

# Create the zip file
archive_name = os.path.dirname(output_zip_path) + "_" + date_string[0:19].replace("T","_").replace(":",".")
#archive_name = os.path.dirname(output_zip_path) + "_" + date_string[0:19].replace("T","_").replace(":",".")

shutil.make_archive(archive_name, 'zip', specific_output_folder_path)
try:
Expand All @@ -164,4 +187,4 @@ def move_files_to_gsba_based_on_gsm_xml(inner_folder_path: str, xml_string: str,


# Delete folders inside the destination with the same name as the now created .gsba file
shutil.rmtree(os.path.dirname(output_zip_path))
shutil.rmtree(output_zip_path) #(os.path.dirname(output_zip_path))
15 changes: 10 additions & 5 deletions gsm_mapping_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ def create_gsm_info_xml_mapping(yaml_contents: dict, output_folder_path: str, re
ET.SubElement(root, 'GameName', IsOfficial="true").text = yaml_contents['name']

date_string = yaml_contents['backups'][0]['when']

inner_backup_folder_name = yaml_contents['backups'][0]['name']

# Add Warning element
ET.SubElement(root, 'Warning')
Expand Down Expand Up @@ -140,7 +142,9 @@ def create_gsm_info_xml_mapping(yaml_contents: dict, output_folder_path: str, re
ET.SubElement(user_info, 'Uplay')

game_name = (yaml_contents['name'].replace(":","")).replace('â„¢', '™')
specific_output_folder = os.path.join(output_folder_path, f"{game_name}")
specific_output_folder = os.path.join(output_folder_path, f"{game_name}" + "_" + date_string[0:19].replace("T","_").replace(":","."))
#specific_output_folder = specific_output_folder + "_" + date_string[0:19].replace("T","_").replace(":",".")


# Registry data processing
#if yaml_contents['backups'][0]['registry']['hash'] != None and registry_yaml_contents != None:
Expand Down Expand Up @@ -183,7 +187,8 @@ def create_gsm_info_xml_mapping(yaml_contents: dict, output_folder_path: str, re

# Write the .reg file
os.makedirs(specific_output_folder, exist_ok=True)
with open(os.path.join(output_folder_path, f"{game_name}", f"{game_name}"+".reg"), 'w') as f:
#with open(os.path.join(output_folder_path, f"{game_name}", f"{game_name}"+".reg"), 'w') as f:
with open(os.path.join(specific_output_folder, f"{game_name}"+".reg"), 'w') as f:
f.write(reg_file_contents)

# Convert the XML structure to a string
Expand All @@ -199,24 +204,24 @@ def create_gsm_info_xml_mapping(yaml_contents: dict, output_folder_path: str, re
# Remove leading whitespace from each line
pretty_xml_string = '\n'.join(line.lstrip() for line in pretty_xml_string.split('\n'))



# Write the pretty-printed XML string to a file
os.makedirs(specific_output_folder, exist_ok=True)

#Check if output folder doesn't have any subfolders with mapping.yaml files inside or if any subfolders' name begins with "backup-"

for root, dirs, files in os.walk(specific_output_folder):
for file in files:
print(os.path.basename(file))
#Compare just file name, not the full path
if os.path.basename(file) == "mapping.yaml":
raise ValueError(f"ERROR: Output folder {specific_output_folder} contains subfolders with 'mapping.yaml' files. These may be Ludusavi backups, that may get overwritten. Please remove them before running the script.")
for dir in dirs:
if dir.startswith("backup-"):
raise ValueError(f"ERROR: Output folder {specific_output_folder} contains subfolders with names starting with 'backup-'. These may be Ludusavi backups, that may get overwritten. Please remove them before running the script.")



with open(os.path.join(specific_output_folder, "GSM_INFO.xml"), 'w') as f:
f.write(pretty_xml_string)

return pretty_xml_string, specific_output_folder, date_string
return pretty_xml_string, specific_output_folder, date_string, inner_backup_folder_name
Loading

0 comments on commit e59cfca

Please sign in to comment.