HOI4_randomchanges/dodo.py
Alexey Chubukov 569a44307e buildable
2023-11-16 00:26:12 +04:00

161 lines
5.6 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 targets(self):
for i in self.keys():
yield self.patchwork_path/i
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 )
)
class ScriptedPatchwork(dict):
def __init__(self, source_file):
with open(source_file) as s:
super().__init__(safe_load(s))
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',
},
patches_path = dir_patches_path,
patchwork_path = dir_patchwork_path
)
patchwork_scripted = ScriptedPatchwork(dir_patches_path/'extrapoint.yaml')
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 source.open(newline='') as infile:
with target.open('w') as outfile:
for line_in in infile:
outfile.write(line_in)
seen_history = seen_history or ( '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 = {\r\n"\
f"\t\t\t{province_id} {province_info['points']}\r\n"\
"\t\t}\r\n"\
)
wrote_history = True
for state_id, state_data in patchwork_scripted.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
}
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.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' ]
}