-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Media versioning #265
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Copyright 2015-2015 the openage authors. See copying.md for legal info. | ||
|
||
# Provides versioning information for converted files. | ||
|
||
|
||
from .gamedata import empiresdat | ||
|
||
print(empiresdat.EmpiresDat.format_hash().hexdigest()) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
add_py_package(openage.pack) | ||
|
||
add_test_py(openage.pack.tests.packcfg_read "tests reading mod pack root config files") | ||
add_test_py(openage.pack.tests.packcfg_write "tests reading mod pack root config files") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
# Copyright 2015-2015 the openage authors. See copying.md for legal info. | ||
|
||
import configparser | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yay configparser! |
||
import re | ||
|
||
|
||
class PackConfig: | ||
""" | ||
main config file for a mod pack. | ||
|
||
stores the package metainformation for the mod list. | ||
|
||
file contents: | ||
|
||
[openage-pack] | ||
name = <package name> | ||
version = <package version> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What precisely is the package version? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was intended to be the revision of the content. But yeah, the name is ambiguous. |
||
author = <pack author> | ||
pack_type = (game|mod|...) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a difference between games and mods? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe a game is a root pack and a mod sits on top of a game or a mod? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, yes, they are probably the same. I thought of this difference because then we could separate the download lists by mods and games. The engine can run Star Wars or AOE and maybe more, and these shouldn't be in the "mod" selection list i think. |
||
config_type = (cfg|nyan|...) | ||
config = <filename.cfg> | ||
""" | ||
|
||
# everything has to be in this section: | ||
root_cfg = "openage-pack" | ||
|
||
# required attributes | ||
pack_attrs = ("name", "version", "author", | ||
"pack_type", "config_type", "config") | ||
|
||
def __init__(self): | ||
""" | ||
init all required attributes to None. | ||
""" | ||
|
||
self.cfg = dict() | ||
|
||
for attr in self.pack_attrs: | ||
self.cfg[attr] = None | ||
|
||
def check_sanity(self): | ||
""" | ||
checks whether the current config is valid. | ||
""" | ||
|
||
if None in self.cfg.values(): | ||
nones = [v for k, v in self.cfg.items() if v is None] | ||
raise Exception("unset attribute(s): %s" % nones) | ||
|
||
if self.cfg["pack_type"] not in ("game", "mod"): | ||
raise Exception("unsupported data pack type") | ||
|
||
if self.cfg["config_type"] not in ("cfg",): | ||
raise Exception("config_type not supported: %s" % | ||
self.cfg["config_type"]) | ||
|
||
if not re.match(r"[a-zA-Z][a-zA-Z0-9_]*", self.cfg["name"]): | ||
raise Exception("disallowed chars in pack name found") | ||
|
||
if not re.match(r"v[0-9]+(\.[0-9]+)*(-r[0-9]+)", self.cfg["version"]): | ||
raise Exception("invalid pack version") | ||
|
||
def read(self, handle): | ||
""" | ||
fill this pack config by the contents provided by the file handle. | ||
""" | ||
|
||
cfp = configparser.ConfigParser() | ||
|
||
# read the config from the (pseudo-?)handle | ||
cfp.read_file(handle, source=handle.name) | ||
|
||
if self.root_cfg not in cfp: | ||
raise Exception("pack root config doesn't contain '%s' section." | ||
% self.root_cfg) | ||
else: | ||
self.cfg = cfp[self.root_cfg] | ||
|
||
self.check_sanity() | ||
|
||
def write(self, handle): | ||
""" | ||
store the settings of this configfile to the given file handle. | ||
""" | ||
|
||
self.check_sanity() | ||
|
||
cfp = configparser.ConfigParser() | ||
cfp[self.root_cfg] = self.cfg | ||
|
||
cfp.write(handle) | ||
|
||
def set_attrs(self, **dct): | ||
""" | ||
set all attributes from the dict to this pack config. | ||
""" | ||
|
||
# just take the known attributes | ||
to_set = {k: v for k, v in dct.items() if k in self.pack_attrs} | ||
|
||
# check if all keys were used | ||
unknown_keys = dct.keys() - to_set.keys() | ||
if unknown_keys: | ||
raise Exception("unknown attr name(s) to set: %s" % unknown_keys) | ||
|
||
self.cfg.update(to_set) | ||
|
||
def get_attrs(self): | ||
""" | ||
return this config's settings. | ||
""" | ||
|
||
return self.cfg |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need to sort the items?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't sort the items, their order is undefined; in practice, it varies from run to run.
The iteration order translates to the order of the segments in the generated C++ code, which will be different with each run, triggering unneeded re-builds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, thought I was still reading the hashing code, not the C++ struct exporting one! now it makes sense lol