mirror of
https://github.com/corpnewt/gibMacOS.git
synced 2025-01-22 10:04:12 -05:00
Add support for running in non-interactive mode
- Exits with non-zero exit status on errors. - Does not hang on prompts. - Just prints text without fancy terminal stuff.
This commit is contained in:
parent
a93490cf99
commit
1e82ba0813
2 changed files with 76 additions and 47 deletions
|
@ -9,8 +9,9 @@ else:
|
||||||
|
|
||||||
class Utils:
|
class Utils:
|
||||||
|
|
||||||
def __init__(self, name = "Python Script"):
|
def __init__(self, name = "Python Script", interactive = True):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.interactive = interactive
|
||||||
# Init our colors before we need to print anything
|
# Init our colors before we need to print anything
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
os.chdir(os.path.dirname(os.path.realpath(__file__)))
|
os.chdir(os.path.dirname(os.path.realpath(__file__)))
|
||||||
|
@ -138,6 +139,8 @@ class Utils:
|
||||||
# returning the result
|
# returning the result
|
||||||
timeout = kwargs.get("timeout", 0)
|
timeout = kwargs.get("timeout", 0)
|
||||||
default = kwargs.get("default", None)
|
default = kwargs.get("default", None)
|
||||||
|
if not self.interactive:
|
||||||
|
return default
|
||||||
# If we don't have a timeout - then skip the timed sections
|
# If we don't have a timeout - then skip the timed sections
|
||||||
if timeout <= 0:
|
if timeout <= 0:
|
||||||
if sys.version_info >= (3, 0):
|
if sys.version_info >= (3, 0):
|
||||||
|
@ -170,11 +173,13 @@ class Utils:
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def cls(self):
|
def cls(self):
|
||||||
os.system('cls' if os.name=='nt' else 'clear')
|
if not self.interactive:
|
||||||
|
return
|
||||||
|
os.system('cls' if os.name=='nt' else 'clear')
|
||||||
|
|
||||||
def cprint(self, message, **kwargs):
|
def cprint(self, message, **kwargs):
|
||||||
strip_colors = kwargs.get("strip_colors", False)
|
strip_colors = kwargs.get("strip_colors", False)
|
||||||
if os.name == "nt":
|
if os.name == "nt" or not self.interactive:
|
||||||
strip_colors = True
|
strip_colors = True
|
||||||
reset = u"\u001b[0m"
|
reset = u"\u001b[0m"
|
||||||
# Requires sys import
|
# Requires sys import
|
||||||
|
@ -216,6 +221,9 @@ class Utils:
|
||||||
|
|
||||||
# Header drawing method
|
# Header drawing method
|
||||||
def head(self, text = None, width = 55):
|
def head(self, text = None, width = 55):
|
||||||
|
if not self.interactive:
|
||||||
|
print(text)
|
||||||
|
return
|
||||||
if text == None:
|
if text == None:
|
||||||
text = self.name
|
text = self.name
|
||||||
self.cls()
|
self.cls()
|
||||||
|
|
109
gibMacOS.py
109
gibMacOS.py
|
@ -2,10 +2,17 @@
|
||||||
from Scripts import downloader,utils,run,plist
|
from Scripts import downloader,utils,run,plist
|
||||||
import os, shutil, time, sys, argparse, re, json
|
import os, shutil, time, sys, argparse, re, json
|
||||||
|
|
||||||
|
class ProgramError(Exception):
|
||||||
|
def __init__(self, message, title = "Error"):
|
||||||
|
super().__init__(message)
|
||||||
|
self.title = title
|
||||||
|
|
||||||
|
|
||||||
class gibMacOS:
|
class gibMacOS:
|
||||||
def __init__(self):
|
def __init__(self, interactive = True):
|
||||||
|
self.interactive = interactive
|
||||||
self.d = downloader.Downloader()
|
self.d = downloader.Downloader()
|
||||||
self.u = utils.Utils("gibMacOS")
|
self.u = utils.Utils("gibMacOS", interactive=interactive)
|
||||||
self.r = run.Run()
|
self.r = run.Run()
|
||||||
self.min_w = 80
|
self.min_w = 80
|
||||||
self.min_h = 24
|
self.min_h = 24
|
||||||
|
@ -73,6 +80,8 @@ class gibMacOS:
|
||||||
)
|
)
|
||||||
|
|
||||||
def resize(self, width=0, height=0):
|
def resize(self, width=0, height=0):
|
||||||
|
if not self.interactive:
|
||||||
|
return
|
||||||
width = width if width > self.min_w else self.min_w
|
width = width if width > self.min_w else self.min_w
|
||||||
height = height if height > self.min_h else self.min_h
|
height = height if height > self.min_h else self.min_h
|
||||||
self.u.resize(width, height)
|
self.u.resize(width, height)
|
||||||
|
@ -84,22 +93,18 @@ class gibMacOS:
|
||||||
try:
|
try:
|
||||||
json.dump(self.settings,open(self.settings_path,"w"),indent=2)
|
json.dump(self.settings,open(self.settings_path,"w"),indent=2)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.u.head("Error Saving Settings")
|
raise ProgramError(
|
||||||
print("")
|
"Failed to save settings to:\n\n{}\n\nWith error:\n\n - {}\n".format(self.settings_path,repr(e)),
|
||||||
print("Failed to save settings to:\n\n{}\n\nWith error:\n\n - {}\n".format(self.settings_path,repr(e)))
|
title="Error Saving Settings")
|
||||||
self.u.grab("Press [enter] to continue...")
|
|
||||||
|
|
||||||
def set_prods(self):
|
def set_prods(self):
|
||||||
self.resize()
|
self.resize()
|
||||||
if not self.get_catalog_data(self.save_local):
|
if not self.get_catalog_data(self.save_local):
|
||||||
self.u.head("Catalog Data Error")
|
message += "The currently selected catalog ({}) was not reachable\n".format(self.current_catalog)
|
||||||
print("")
|
|
||||||
print("The currently selected catalog ({}) was not reachable".format(self.current_catalog))
|
|
||||||
if self.save_local:
|
if self.save_local:
|
||||||
print("and I was unable to locate a valid {} file in the\n{} directory.".format(self.plist, self.scripts))
|
message += "and I was unable to locate a valid {} file in the\n{} directory.\n".format(self.plist, self.scripts)
|
||||||
print("Please ensure you have a working internet connection.")
|
message += "Please ensure you have a working internet connection."
|
||||||
print("")
|
raise ProgramError(message, title="Catalog Data Error")
|
||||||
self.u.grab("Press [enter] to exit...")
|
|
||||||
self.u.head("Parsing Data")
|
self.u.head("Parsing Data")
|
||||||
print("")
|
print("")
|
||||||
print("Scanning products after catalog download...\n")
|
print("Scanning products after catalog download...\n")
|
||||||
|
@ -297,12 +302,7 @@ class gibMacOS:
|
||||||
# add it to the list
|
# add it to the list
|
||||||
dl_list.append(x["URL"])
|
dl_list.append(x["URL"])
|
||||||
if not len(dl_list):
|
if not len(dl_list):
|
||||||
self.u.head("Error")
|
raise ProgramError("There were no files to download")
|
||||||
print("")
|
|
||||||
print("There were no files to download")
|
|
||||||
print("")
|
|
||||||
self.u.grab("Press [enter] to return...")
|
|
||||||
return
|
|
||||||
c = 0
|
c = 0
|
||||||
done = []
|
done = []
|
||||||
if self.print_urls:
|
if self.print_urls:
|
||||||
|
@ -310,8 +310,9 @@ class gibMacOS:
|
||||||
print("")
|
print("")
|
||||||
print("{}:\n".format(name))
|
print("{}:\n".format(name))
|
||||||
print("\n".join([" - {} \n --> {}".format(os.path.basename(x), x) for x in dl_list]))
|
print("\n".join([" - {} \n --> {}".format(os.path.basename(x), x) for x in dl_list]))
|
||||||
print("")
|
if self.interactive:
|
||||||
self.u.grab("Press [enter] to return...")
|
print("")
|
||||||
|
self.u.grab("Press [enter] to return...")
|
||||||
return
|
return
|
||||||
# Only check the dirs if we need to
|
# Only check the dirs if we need to
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
|
@ -322,6 +323,8 @@ class gibMacOS:
|
||||||
print("")
|
print("")
|
||||||
print("It looks like you've already downloaded {}".format(name))
|
print("It looks like you've already downloaded {}".format(name))
|
||||||
print("")
|
print("")
|
||||||
|
if not self.interactive:
|
||||||
|
return
|
||||||
menu = self.u.grab("Redownload? (y/n): ")
|
menu = self.u.grab("Redownload? (y/n): ")
|
||||||
if not len(menu):
|
if not len(menu):
|
||||||
continue
|
continue
|
||||||
|
@ -371,7 +374,10 @@ class gibMacOS:
|
||||||
print("Files saved to:")
|
print("Files saved to:")
|
||||||
print(" {}".format(os.path.join(os.getcwd(), self.saves, self.current_catalog, name)))
|
print(" {}".format(os.path.join(os.getcwd(), self.saves, self.current_catalog, name)))
|
||||||
print("")
|
print("")
|
||||||
self.u.grab("Press [enter] to return...")
|
if self.interactive:
|
||||||
|
self.u.grab("Press [enter] to return...")
|
||||||
|
elif len(failed):
|
||||||
|
raise ProgramError("{} files failed to download".format(len(failed)))
|
||||||
|
|
||||||
def show_catalog_url(self):
|
def show_catalog_url(self):
|
||||||
self.resize()
|
self.resize()
|
||||||
|
@ -381,9 +387,9 @@ class gibMacOS:
|
||||||
print("Max macOS Version: {}".format(self.num_to_macos(self.current_macos,for_url=False)))
|
print("Max macOS Version: {}".format(self.num_to_macos(self.current_macos,for_url=False)))
|
||||||
print("")
|
print("")
|
||||||
print("{}".format(self.build_url()))
|
print("{}".format(self.build_url()))
|
||||||
print("")
|
if self.interactive:
|
||||||
menu = self.u.grab("Press [enter] to return...")
|
print("")
|
||||||
return
|
self.u.grab("Press [enter] to return...")
|
||||||
|
|
||||||
def pick_catalog(self):
|
def pick_catalog(self):
|
||||||
self.resize()
|
self.resize()
|
||||||
|
@ -540,8 +546,7 @@ class gibMacOS:
|
||||||
if device_id:
|
if device_id:
|
||||||
prod = next(p for p in prods if device_id.lower() in p["device_ids"])
|
prod = next(p for p in prods if device_id.lower() in p["device_ids"])
|
||||||
if not prod:
|
if not prod:
|
||||||
print("No version found for Device ID '{}'".format(device_id))
|
raise ProgramError("No version found for Device ID '{}'".format(device_id))
|
||||||
return
|
|
||||||
else:
|
else:
|
||||||
prod = prods[0]
|
prod = prods[0]
|
||||||
self.download_prod(prod, dmg)
|
self.download_prod(prod, dmg)
|
||||||
|
@ -553,7 +558,7 @@ class gibMacOS:
|
||||||
if p["product"] == prod:
|
if p["product"] == prod:
|
||||||
self.download_prod(p, dmg)
|
self.download_prod(p, dmg)
|
||||||
return
|
return
|
||||||
print("{} not found".format(prod))
|
raise ProgramError("{} not found".format(prod))
|
||||||
|
|
||||||
def get_for_version(self, vers, build = None, device_id = None, dmg = False):
|
def get_for_version(self, vers, build = None, device_id = None, dmg = False):
|
||||||
self.u.head("Downloading for {} {}".format(vers, build or ""))
|
self.u.head("Downloading for {} {}".format(vers, build or ""))
|
||||||
|
@ -593,7 +598,7 @@ class gibMacOS:
|
||||||
if (n in pt) and not len(name_match):
|
if (n in pt) and not len(name_match):
|
||||||
self.download_prod(p, dmg)
|
self.download_prod(p, dmg)
|
||||||
return
|
return
|
||||||
print("'{}' '{}' not found".format(vers, build))
|
raise ProgramError("'{}' '{}' not found".format(vers, build or ""))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
@ -609,9 +614,10 @@ if __name__ == '__main__':
|
||||||
parser.add_argument("-m", "--maxos", help="sets the max macOS version to consider when building the url - eg 10.14")
|
parser.add_argument("-m", "--maxos", help="sets the max macOS version to consider when building the url - eg 10.14")
|
||||||
parser.add_argument("-D", "--device-id", help="use with --version or --latest to search for versions supporting the specified Device ID - eg VMM-x86_64 for any x86_64")
|
parser.add_argument("-D", "--device-id", help="use with --version or --latest to search for versions supporting the specified Device ID - eg VMM-x86_64 for any x86_64")
|
||||||
parser.add_argument("-i", "--print-urls", help="only prints the download URLs, does not actually download them", action="store_true")
|
parser.add_argument("-i", "--print-urls", help="only prints the download URLs, does not actually download them", action="store_true")
|
||||||
|
parser.add_argument("--no-interactive", help="run in non-interactive mode", action="store_true")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
g = gibMacOS()
|
g = gibMacOS(interactive=not args.no_interactive)
|
||||||
if args.recovery:
|
if args.recovery:
|
||||||
args.dmg = False
|
args.dmg = False
|
||||||
g.find_recovery = args.recovery
|
g.find_recovery = args.recovery
|
||||||
|
@ -635,18 +641,33 @@ if __name__ == '__main__':
|
||||||
# Set the catalog
|
# Set the catalog
|
||||||
g.set_catalog(args.catalog)
|
g.set_catalog(args.catalog)
|
||||||
|
|
||||||
# Done setting up pre-requisites
|
try:
|
||||||
g.set_prods()
|
# Done setting up pre-requisites
|
||||||
|
g.set_prods()
|
||||||
|
|
||||||
if args.latest:
|
if args.latest:
|
||||||
g.get_latest(device_id=args.device_id, dmg=args.dmg)
|
g.get_latest(device_id=args.device_id, dmg=args.dmg)
|
||||||
exit()
|
elif args.product != None:
|
||||||
if args.product != None:
|
g.get_for_product(args.product, args.dmg)
|
||||||
g.get_for_product(args.product, args.dmg)
|
elif args.version != None:
|
||||||
exit()
|
g.get_for_version(args.version, args.build, device_id=args.device_id, dmg=args.dmg)
|
||||||
if args.version != None:
|
elif g.interactive:
|
||||||
g.get_for_version(args.version, args.build, device_id=args.device_id, dmg=args.dmg)
|
while True:
|
||||||
exit()
|
try:
|
||||||
|
g.main(args.dmg)
|
||||||
while True:
|
except ProgramError as e:
|
||||||
g.main(args.dmg)
|
g.u.head(e.title)
|
||||||
|
print("")
|
||||||
|
print(str(e))
|
||||||
|
print("")
|
||||||
|
g.u.grab("Press [enter] to return...")
|
||||||
|
else:
|
||||||
|
raise ProgramError("No command specified")
|
||||||
|
except ProgramError as e:
|
||||||
|
print(str(e))
|
||||||
|
if g.interactive:
|
||||||
|
print("")
|
||||||
|
g.u.grab("Press [enter] to exit...")
|
||||||
|
else:
|
||||||
|
exit(1)
|
||||||
|
exit(0)
|
||||||
|
|
Loading…
Reference in a new issue