HOI4_randomchanges/dodo.py
2023-11-12 21:40:03 +04:00

172 lines
6.5 KiB
Python

#!/usr/bin/env python3
from pathlib import Path
from yaml import safe_load
def files(p):
for i in p:
if i.is_file():
yield i
class Patchwork(dict):
patches_path = None
patchwork_path = None
def __init__(self, *arkg, **kwargs):
self.patches_path = Path(kwargs.pop("patches_path"))
self.patchwork_path = Path(kwargs.pop("patchwork_path"))
super().__init__(*arkg, **kwargs)
patchwork_mkdir = 'mkdir -p {}/{}'
def prerequisites(self, vanilla_path):
for i in self.values():
yield self.patches_path/i
for i in self.keys():
yield vanilla_path/i
def targets(self):
for i in self.keys():
yield self.patchwork_path/i
def action_generator(self, key, value, vanilla_path):
yield f"mkdir -p {self.patchwork_path}/{Path(key).parent}"
yield f"patch -u --binary -N -o '{self.patchwork_path}/{key}' "\
f"'{vanilla_path}/{key}' '{self.patches_path}/{value}'"
def actions(self, vanilla_path):
for k, v in self.items():
yield from self.action_generator(k, v, vanilla_path)
def tasks(self, vanilla_path):
for k, v in self.items():
yield (
[ self.patches_path/v, vanilla_path/k ], # src ( patch file, orig file )
[ self.patchwork_path/k ], #dst ( patched file )
[
f"mkdir -p {self.patchwork_path}/{Path(k).parent}",
f"patch -u --binary -N -o '{self.patchwork_path}/{k}' "\
f"'{vanilla_path}/{k}' '{self.patches_path}/{v}'"
] # action ( mkdir, patch )
)
mod_name = 'randchgs'
mod_install_path = 'C:/Users/User/Documents/Paradox Interactive/Hearts of Iron IV/mod/randchgs'
dir_vanilla = Path("../vanilla/v1.13.4")
dir_image = Path('build/image')
dir_modimage = Path(f"{dir_image}/{mod_name}")
dir_src_raw = Path('src/raw')
dir_src_raw_files = list(files(Path(dir_src_raw).rglob("*")))
dir_patches_path = Path('src/patches')
dir_patchwork_path = Path('build/patched')
patchwork = Patchwork({
'map/definition.csv': 'map_definition.patch',
'history/countries/ISR - Israel.txt': 'history_countries_ISR.patch',
# 'history/states/728-Guangzhouwan.txt' : 'history_states_728.patch',
}, patches_path = dir_patches_path, patchwork_path = dir_patchwork_path )
patchwork_scripted_template_input_file = dir_patches_path/'extrapoint.yaml'
with open(patchwork_scripted_template_input_file) as s:
patchwork_scripted_template_input_data = safe_load(s)
dir_image_files = [ f"{dir_modimage}/{f.relative_to(dir_src_raw)}" for f in dir_src_raw_files ] + \
[ f"{dir_modimage}/{f.relative_to(patchwork.patchwork_path)}" for f in patchwork.targets() ]
DOIT_CONFIG = {
'default_tasks': ['build'],
'action_string_formatting': 'both'
}
def history_states_path(state_id):
history_state_file = next((Path(dir_vanilla)/'history'/'states').glob(f"{state_id}*"))
return {
'src' : history_state_file,
'dest': Path(dir_patchwork_path)/history_state_file.relative_to(dir_vanilla)
}
def task_patch_history_states_scripted():
def history_state_patch(task, provinces):
source = Path(next(iter(task.file_dep)))
target = Path(task.targets[0])
target.parent.mkdir(parents=True, exist_ok=True)
seen_history = False
wrote_history = False
with target.open('w') as outfile:
with source.open() as infile:
for line_in in infile:
outfile.write(line_in)
seen_history = 'history' in line_in
if not wrote_history and seen_history and '{' in line_in:
for province_id, province_info in provinces.items():
outfile.write(
"\t\tvictory_points = {\n"\
f"\t\t\t{province_id} {province_info['points']}\n"\
"\t\t}\n"\
)
wrote_history = True
target.touch()
for state_id, state_data in patchwork_scripted_template_input_data.items():
files = history_states_path(state_id)
yield {
'name' : f"{state_id}",
'file_dep' : [ files['src'] ],
'targets' : [ files['dest'] ],
'actions' : [ ( history_state_patch, [], {'provinces' : state_data}) ],
'clean' : True
}
def task_patch():
for src, dest, patch in patchwork.tasks(dir_vanilla):
yield {
'name' : f"{dest[0]}",
'file_dep' : src,
'targets' : dest,
'actions' : patch,
'clean' : True
}
# return {
# 'file_dep' : list(patchwork.prerequisites(dir_vanilla)),
# 'targets' : list(patchwork.targets()),
# 'actions' : list(patchwork.actions(dir_vanilla)),
# 'clean' : True
# }
def task_image():
filelist = dir_src_raw_files + list(patchwork.targets())
return {
'file_dep' : filelist +
[ history_states_path(state_id)['dest']
for state_id in patchwork_scripted_template_input_data.keys() ],
'targets' : dir_image_files,
'actions' : [f"mkdir -p {dir_modimage}",
f"rsync -rv {dir_src_raw}/ {patchwork.patchwork_path}/"\
f" {dir_modimage}/" ],
'clean' : True
}
def task_image_mod():
dep = 'src/raw/descriptor.mod'
def prepare_modname_mod(task):
source = Path(next(iter(task.file_dep)))
target = Path(task.targets[0])
target.parent.mkdir(parents=True, exist_ok=True)
with source.open() as s:
with target.open('w') as o:
o.write(s.read())
o.write(f"path=\"{mod_install_path}\"")
return {
'file_dep' : [ dep ],
'targets' : [f"{dir_image}/{mod_name}.mod" ],
'actions' : [ prepare_modname_mod ],
'clean' : True
}
def task_build():
return {
'task_dep' : [ 'image' ],
'file_dep' : [f"{dir_image}/{mod_name}.mod" ] + dir_image_files,
'targets' : [f"{dir_image}/{mod_name}.zip" ],
'actions' : [f"cd {dir_image} && zip -r {mod_name}.zip {mod_name}",
f"cd {dir_image} && zip -r {mod_name}.zip {mod_name}.mod" ],
'clean' : True
}
def task_purge_build():
return {
'actions' : [ 'rm -rf build' ]
}