172 lines
6.5 KiB
Python
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' ]
|
|
}
|