forked from SFTtech/openage
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add manifest file creator for a modpack
- Loading branch information
Showing
4 changed files
with
118 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
# Copyright 2020-2020 the openage authors. See copying.md for legal info. | ||
|
||
""" | ||
Create a manifest file for a modpack | ||
""" | ||
import hashlib | ||
import os | ||
import toml | ||
|
||
from ....util.fslike.path import Path | ||
from ...entity_object.export.data_definition import DataDefinition | ||
|
||
|
||
class ManifestFile(DataDefinition): | ||
""" | ||
Used for creating a manifest file for a modpack. | ||
""" | ||
|
||
HASHING_FUNCTION = 'sha3_256' | ||
BUF_SIZE = 32000 | ||
|
||
def __init__(self, targetdir, filename): | ||
super().__init__(targetdir, filename) | ||
|
||
def dump(self, exportdir): | ||
""" | ||
Returns the manifest file content in TOML format. | ||
:param exportdir: directory which contains exported modpack | ||
:type exportdir: ....util.fslike.path.Path | ||
""" | ||
|
||
output_dict = {} | ||
|
||
info_table = {"info": {}} | ||
info_table["info"].update({"hash": self.HASHING_FUNCTION}) | ||
|
||
output_dict.update(info_table) | ||
|
||
hash_values_table = {'hash-values': {}} | ||
for file in self._bfs_directory(exportdir): | ||
hash_val = self._get_file_hash(file) | ||
relative_path = os.path.relpath(str(file), str(exportdir)) | ||
hash_values_table['hash-values'].update({hash_val: relative_path}) | ||
|
||
output_dict.update(hash_values_table) | ||
|
||
output_str = "# openage autogenerated modpack integrity check\n\n" | ||
output_str += toml.dumps(output_dict) | ||
|
||
return output_str | ||
|
||
def save(self, exportdir): | ||
""" | ||
Saves the contents of the manifest file in the exported | ||
directory containing the modpack. | ||
:param exportdir: Relative path to the export directory. | ||
:type exportdir: ....util.fslike.path.Path | ||
""" | ||
if not isinstance(exportdir, Path): | ||
raise ValueError("util.fslike.path.Path expected as filename, not %s" % | ||
type(exportdir)) | ||
|
||
output_dir = exportdir.joinpath(self.targetdir) | ||
output_content = self.dump(exportdir) | ||
|
||
# generate human-readable file | ||
with output_dir[self.filename].open('wb') as outfile: | ||
outfile.write(output_content.encode('utf-8')) | ||
|
||
def _bfs_directory(self, root): | ||
""" | ||
Traverse the given directory in breadth-first way. | ||
:param root: The directory to traverse. | ||
:type root: ....util.fslike.path.Path | ||
""" | ||
|
||
dirs = [root] | ||
while dirs: | ||
next_level = [] | ||
for directory in dirs: | ||
for item in directory.iterdir(): | ||
item_path = directory.joinpath(item) | ||
if item_path.is_dir(): | ||
next_level.append(item_path) | ||
else: | ||
yield item_path | ||
dirs = next_level | ||
|
||
def _get_file_hash(self, file_path): | ||
""" | ||
Returns the hash value of a given file. | ||
:param file_path: Path of the given file. | ||
:type file_path: ....util.fslike.path | ||
""" | ||
# set the hashing algorithm | ||
hashf = hashlib.new(self.HASHING_FUNCTION) | ||
|
||
with file_path.open_r() as f_in: | ||
while True: | ||
data = f_in.read(self.BUF_SIZE) | ||
if not data: | ||
break | ||
hashf.update(data) | ||
|
||
return hashf.hexdigest() |