diff --git a/config.json b/config.json new file mode 100644 index 0000000..bfec8ff --- /dev/null +++ b/config.json @@ -0,0 +1,8 @@ +{ + "baseUrl": "https://git.m724.eu/Minecon724/giants-metadata/raw/branch/master", + "defaultChannel": "release", + "maven": { + "repo": "https://git.m724.eu/api/packages/Minecon724/maven", + "package": "eu.m724:giants" + } +} \ No newline at end of file diff --git a/release.py b/release.py old mode 100644 new mode 100755 index 1701f28..114f529 --- a/release.py +++ b/release.py @@ -1,10 +1,10 @@ #!/usr/bin/python3 import json, os, time, tempfile, shutil +import argparse, urllib.request from hashlib import sha256 META_FILENAME = 'meta-v1.json' -BASE_URL = open('url.txt').read().strip() BASE_DIR = 'data' WAITING_DIR = 'pending' TEMP_DIR = tempfile.TemporaryDirectory() @@ -79,24 +79,6 @@ def make_path(channel: str, version: str=None, filename: str=None) -> str: args = [i for i in args if i is not None] return os.path.join(BASE_DIR, *args) -def list_channels() -> list[str]: - return next(os.walk(BASE_DIR))[1] - -# verification functions - -def channel_exists(channel: str) -> bool: - """Checks if channel exists""" - return os.path.isdir(make_path(channel)) - -def check_version_exists(version: str) -> str | None: - """ - Check if version exists in any channel. - If yes, returns that channel, otherwise None - """ - for channel in list_channels(): - if os.path.isdir(make_path(channel, version)): - return channel - # metadata functions def load_latest_data(channel: str) -> dict: @@ -113,7 +95,8 @@ def write_metadata(channel: str, metadata: dict): file.write(metadata) def commit_and_push(channel: str, version: str): - os.system('git add .') + os.system(f'git add data/{channel}/latest') + os.system(f'git add data/{channel}/{version}') os.system(f'git commit -m "[releaser] Release {version} on {channel}"') os.system('git push') @@ -127,57 +110,121 @@ def hash_file(filepath: str) -> str: with open(filepath, 'rb') as file: return sha256(file.read()).hexdigest() +def download_and_hash(url: str) -> str: + sha256_hash = sha256() + + try: + print(f"Downloading and hashing {url}...") + with urllib.request.urlopen(url) as response: + # Read and hash in chunks to handle large files efficiently + while True: + chunk = response.read(4096) # 4KB chunks + if not chunk: + break + sha256_hash.update(chunk) + + return sha256_hash.hexdigest() + + except Exception as e: + raise Exception(f"Download or hashing failed: {str(e)}") + # main -def main(): - channel = input('Channel? ({}) '.format(', '.join(list_channels()))) - if channel == '' or not channel_exists(channel): - print(f"Channel {channel} doesn't exist") - return +def main(config: dict, version: str, channel: str, local: bool): + file_url = None + file_hash = None - version = input('New version? ') - exists_in = check_version_exists(version) - if exists_in is not None: - print(f"This version already exists in channel {exists_in}. Choose a different version.") - return + changelog = confirm('Do you want to include a changelog?') + if changelog: + chlog_filepath, chlog_filename = just_find_file('changelog.txt') - jar_filepath, jar_filename = just_find_file('jar') + latest_data = load_latest_data(channel) + version_dir = make_path(channel, version) - changelog = confirm('Do you want to include a changelog?') - if changelog: - chlog_filepath, chlog_filename = just_find_file('changelog.txt') + os.makedirs(make_path(channel, 'latest'), exist_ok=True) + os.mkdir(version_dir) + + if changelog: shutil.move(chlog_filepath, os.path.join(version_dir, 'changelog.txt')) - # + if local: + jar_filepath, jar_filename = just_find_file('jar') - latest_data = load_latest_data(channel) - hash = hash_file(jar_filepath) + file_hash = hash_file(jar_filepath) + file_url = f'{config["baseUrl"]}/{BASE_DIR}/{channel}/{version}/{jar_filename}' - version_dir = make_path(channel, version) + shutil.move(jar_filepath, os.path.join(version_dir, jar_filename)) + else: + groupId, artifactId = config["maven"]["package"].split(':') + file_url = config["maven"]["repo"] + f"/{groupId.replace('.', '/')}/{artifactId}/{version}/{artifactId}-{version}.jar" + file_hash = download_and_hash(file_url) - os.makedirs(make_path(channel, 'latest'), exist_ok=True) - os.mkdir(version_dir) - shutil.move(jar_filepath, os.path.join(version_dir, jar_filename)) - if changelog: shutil.move(chlog_filepath, os.path.join(version_dir, 'changelog.txt')) + metadata = { + 'label': version, + 'id': latest_data['id'] + 1, + 'timestamp': int(time.time()), + 'file': file_url, + 'sha256': file_hash + } - metadata = { - 'label': version, - 'id': latest_data['id'] + 1, - 'timestamp': int(time.time()), - 'file': f'{BASE_URL}/{BASE_DIR}/{channel}/{version}/{jar_filename}', - 'sha256': hash - } + write_metadata(channel, metadata) - write_metadata(channel, metadata) + try: + os.rmdir(WAITING_DIR) + except FileNotFoundError: + pass - try: - os.rmdir(WAITING_DIR) - except FileNotFoundError: - pass + if confirm("Commit and push?"): + commit_and_push(channel, version) - if confirm("Commit and push?"): - commit_and_push(channel, version) - - print("Done") + print("Done") if __name__ == "__main__": - main() + config = json.loads(open('config.json', 'r').read()) + channels = [c.strip() for c in open(os.path.join('data', 'channels.txt'))] + + parser = argparse.ArgumentParser( + description='Release', + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + + parser.add_argument('version', + help='The version to release') + + parser.add_argument('-c', '--channel', + default=config["defaultChannel"], + choices=channels, + help='Release channel') + + parser.add_argument('-l', '--local', + action='store_true', + help='From local file instead of repo') + + args = parser.parse_args() + version = args.version + channel = args.channel + local = args.local + + if version == "latest": + print("Version can't be \"latest\"") + exit() + + def check_version_exists(version: str) -> str | None: + """ + Check if version exists in any channel. + If yes, returns that channel, otherwise None + """ + for channel in list_channels(): + if os.path.isdir(make_path(channel, version)): + return channel + + existing = [c for c in channels if os.path.isdir(make_path(c, version))] + + if channel in existing: + print(f"Version {version} already exists in channel {channel}.") + exit() + + if len(existing) > 0: + if not confirm(f"Version {version} already exists in \"{', '.join(existing)}\". Do you still want to proceed?"): + exit() + + main(config, version, channel, local) diff --git a/url.txt b/url.txt deleted file mode 100644 index b5e9c85..0000000 --- a/url.txt +++ /dev/null @@ -1 +0,0 @@ -https://git.m724.eu/Minecon724/giants-metadata/raw/branch/master