From ce4cb0b5cd157c77396344958b403c41a4f0f8b3 Mon Sep 17 00:00:00 2001 From: duvallj Date: Sat, 2 Feb 2019 13:32:01 -0500 Subject: Update update.py (better argument parsing, documentation) --- update.py | 179 +++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 114 insertions(+), 65 deletions(-) (limited to 'update.py') diff --git a/update.py b/update.py index 373a839..a04df5c 100755 --- a/update.py +++ b/update.py @@ -1,97 +1,146 @@ #!/usr/bin/env python3 -import hashlib -import requests + +import argparse +import textwrap import os -import shutil import sys +import hashlib +import shutil + +import requests +import colorama +from termcolor import colored -# Initalize from config -INSTALL_DIR = "" -with open("pack-location.txt", "r") as f: - INSTALL_DIR = f.read().strip() +parser = argparse.ArgumentParser( + description="A Simple Git-Based Modpack Manager", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog='''\ +Available commands: + install : Downloads mods listed in downloads.txt and populates the mods folder specified in pack-location.txt + apply_updates : Using the latest downloads in latest-urls.txt, repopulates downloads.txt to reflect the most recent mod versions + check_updates : Compares downloads.txt and latest-urls.txt to see if any mods can be updated +''') +parser.add_argument('command', + nargs='?', + default='install', + help="The action to perform (default: install)") +parser.add_argument('filename', + nargs='?', + default="mods.txt", + help="Optional filename to specify latest mods (default: mods.txt)") +parser.add_argument('--url-file', + type=str, + default="downloads.txt", + help="Optional custom URL file to download mods from (default: downloads.txt)") +parser.add_argument('--pack-location', + type=str, + help="Optional custom modpack folder location (default: read from pack-location.txt)") + +def read_file(fil): + strings = [] + with open(fil) as f: + for line in f: + string = line.strip().split() + if len(line) > 1 and line[0] != '#': + # run strip on each element + string = tuple(map(lambda x: x.strip(), string)) + strings.append(string) + return strings # Apply updates to the actual mod pack -def install(): - print("Updating pack...") +def install(args): + print(colored("Updating pack...", 'green', attrs=['bold'])) # (fname, checksum, url) - mods = read_file("downloads.txt") + mods = read_file(args.url_file) names = [mod[0] for mod in mods] + for mod in mods: - if mod[0] in os.listdir(INSTALL_DIR) and hashlib.sha1(open(os.path.join(INSTALL_DIR, mod[0]), 'rb').read()).hexdigest() == mod[1]: - print("Skipping " + mod[0] + ", already up to date") + mod_path = os.path.join(args.pack_location, mod[0]) + if os.path.exists(mod_path) and os.path.isfile(mod_path) and \ + hashlib.sha1(open(mod_path, 'rb').read()).hexdigest() == mod[1]: + print("Skipping {mod[0]}, already up to date".format(mod=mod)) else: - print(f'Installing {mod[0]} from {mod[2]}...') + print(colored('Installing {mod[0]} from {mod[2]}...'.format(mod=mod), attrs=['bold'])) download_obj = requests.get(mod[2], stream=True) - with open(os.path.join(INSTALL_DIR, mod[0]), "wb") as write_file: + with open(mod_path, "wb") as write_file: shutil.copyfileobj(download_obj.raw, write_file) print("Done!") - print("\nRemoving old versions...") - for jar in os.listdir(INSTALL_DIR): + print() + print(colored("Removing old mods...", 'green', attrs=['bold'])) + + for jar in os.listdir(args.pack_location): if jar not in names and os.path.splitext(jar)[1] == ".jar": - os.remove(os.path.join(INSTALL_DIR, jar)) - print(f"Removing '{jar}'") + os.remove(os.path.join(args.pack_location, jar)) + print(colored("Removing '{jar}'".format(jar=jar), attrs=['bold'])) - print("\nFinished installing mods!") + print() + print(colored("Finished installing mods!", 'green', attrs=['bold'])) # Using the latest urls, update downloads.txt to match the urls and have the correct sha1 -def apply_updates(): - print("Populating downloads.txt...") - mods = read_file("latest-urls.txt") - print("Getting new versions of all mods...") - with open('downloads.txt', 'w') as f: +def apply_updates(args): + print(colored("Populating URL File...", 'green', attrs=['bold'])) + mods = read_file(args.filename) + print(colored("Getting new versions of all mods...", attrs=['bold'])) + with open(args.url_file, 'w') as f: f.write('# Format: \n') for mod in mods: - print(f"Fetching {mod[0]}...") + print("Fetching {mod[0]}...".format(mod=mod)) resp = requests.get(mod[1]) - hsh = hashlib.sha1(resp.content) - f.write(f'{mod[0]} {hsh.hexdigest()} {resp.url}\n') - print("\nDone!\nUpdates applied to downloads.txt") - print("[!] No mods were installed. To update your mods folder, run 'update.py install'") + hsh = hashlib.sha1(resp.content).hexdigest() + f.write('{mod[0]} {hsh} {resp.url}\n'.format(mod=mod, hsh=hsh, resp=resp)) + print() + print("Done!") + print(colored("Updates applied to downloads.txt", 'green', attrs=['bold'])) + print(colored("[!] No mods were installed. To update your mods folder, run 'update.py install'", 'white', 'on_red', attrs=['bold', 'underline'])) # Find if any updates are available -def check_updates(): - print("check_updates: Checking for updates to mods...") - latest = read_file("latest-urls.txt") - old = read_file("downloads.txt") +def check_updates(args): + print(colored("Checking for updates to mods...", 'green', attrs=['bold'])) + latest = read_file(args.filename) + old = read_file(args.url_file) old_urls = [mod[2] for mod in old] - print("Checking updates...\nThe following mods have updates available:\n") + print(colored("Checking updates...", attrs=['bold'])) for mod in latest: - print(f"Checking for updates to {mod[0]}..." + " " * 35,end="\r") + print('\033[2K',end="") # ANSI code to clear line + print("Checking for updates to {mod[0]}...".format(mod=mod),end="\r") resp = requests.get(mod[1]) if not resp.url in old_urls: - print(f" -> Found update for {mod[0]}: {resp.url.split('/')[-1]}") - print("Finished checking for updates!" + " " * 35) - -def read_file(fil): - strings = [] - with open(fil) as f: - for line in f: - string = line.strip().split() - if len(line) > 1 and line[0] != '#': - # run strip on each element - string = tuple(map(lambda x: x.strip(), string)) - strings.append(string) - return strings + print(colored(" -> Found update for {mod[0]}: {resp.url.split('/')[-1]}".format(mod=mod, resp=resp), attrs=['bold'])) + + print('\033[2K' + colored("Finished checking for updates!", attrs=['bold'])) +COMMAND_MAP = { + 'install': install, + 'apply_updates': apply_updates, + 'check_updates': check_updates, +} -if len(sys.argv) < 2: - #install by default - install() -elif sys.argv[1] == 'install': - install() -elif sys.argv[1] == 'apply_updates': - apply_updates() -elif sys.argv[1] == 'check_updates': - check_updates() -elif 'h' in sys.argv[1]: - print(f"Usage: {sys.argv[0]} ") - print(" install\tdownloads mods listed in downloads.txt and populates the mods folder specified in pack-location.txt") - print(" apply_updates\tusing the latest downloads in latest-urls.txt, repopulates downloads.txt to reflect the most recent mod versions") - print(" check_updates\tcompares downloads.txt and latest-urls.txt to see if any mods can be updated") -else: - print(f"Usage: {sys.argv[0]} ") - sys.exit(-1) +if __name__ == "__main__": + colorama.init() + args = parser.parse_args() + + if not args.pack_location: + # initialize from config + with open("pack-location.txt", "r") as f: + args.pack_location = f.read().strip() + + if not os.path.exists(args.pack_location): + print(colored("Error: mod folder \"" + args.pack_location + "\" does not exist.", 'red', attrs=['bold'])) + parser.print_help() + sys.exit(1) + elif not os.path.isdir(args.pack_location): + print(colored("Error: mod folder \"" + args.pack_location + "\" is not actually a folder.", 'red', attrs=['bold'])) + parser.print_help() + sys.exit(1) + + if not (args.command in COMMAND_MAP): + print(colored("Error: command \"" + args.command + "\" does not exist", 'red', attrs=['bold'])) + parser.print_help() + sys.exit(1) + + # run the command + COMMAND_MAP[args.command](args) -- cgit v1.2.3