1
0
mirror of https://github.com/foxlet/macOS-Simple-KVM.git synced 2024-06-02 06:03:31 +02:00

[TOOLS] Support downloading all releases at once

This commit is contained in:
Andrea Pascal 2019-07-22 01:26:14 -05:00
parent b51ffa63af
commit 99d08b8da6
2 changed files with 86 additions and 35 deletions

View File

@ -12,6 +12,7 @@ print_usage() {
echo " -s, --high-sierra Fetch High Sierra media."
echo " -m, --mojave Fetch Mojave media."
echo " -c, --catalina Fetch Catalina media."
echo " -a, --all Fetch ALL media."
echo
}
@ -31,6 +32,14 @@ case $argument in
-c|--catalina|*)
$TOOLS/FetchMacOS/fetch.sh -l -c DeveloperSeed || exit 1;
;;
-a|--all)
$TOOLS/FetchMacOS/fetch.sh -a -k BaseSystem || exit 1;
for p in $(ls -1 $TOOLS/FetchMacOS/SoftwareUpdate/) do
dmg2img $TOOLS/FetchMacOS/SoftwareUpdate/$p/BaseSystem.dmg $TOOLS/FetchMacOS/SoftwareUpdate/$p/BaseSystem.img;
done;
echo "NOTE: Because you chose to download ALL media instead of a specific version, you can find each image in ./tools/FetchMacOS/SoftwareUpdate/\$VERSION/BaseSystem.img instead of the default location."
;;
-h|--help)
print_usage
;;

View File

@ -9,6 +9,7 @@ import errno
import click
import requests
import sys
import re
__author__ = "Foxlet"
__copyright__ = "Copyright 2019, FurCode Project"
@ -59,28 +60,48 @@ class SoftwareService:
"PublicRelease13":"https://swscan.apple.com/content/catalogs/others/index-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog"}
def __init__(self, catalog_id):
self.catalog_url = self.catalogs.get(catalog_id, self.catalogs["PublicRelease"])
self.catalog_data = ""
self.catalog_data = list()
self.catalog_url = list()
def getcatalog(self):
logging.info("Network Request: %s", "Fetching {}".format(self.catalog_url))
catalog_raw = requests.get(self.catalog_url, headers=ClientMeta.swupdate)
self.catalog_data = catalog_raw.text.encode('UTF-8')
return catalog_raw.text.encode('UTF-8')
if catalog_id == "__ALL__":
# Automatically generate each version's catalog URL from the latest
match = re.match(r'(https://swscan.apple.com/content/catalogs/others/index-)([\w.-]+)(\.merged-1\.sucatalog)', self.catalogs.get("DeveloperSeed"))
releases = match.group(2).split('-')
for i in range(len(releases)):
self.catalog_url.append(match.group(1) + str().join([x + '-' for x in releases]).rstrip('-') + match.group(3))
releases.remove(releases[0])
else:
self.catalog_url.append(self.catalogs.get(catalog_id))
def getcatalogs(self):
self.catalog_raw = list()
for url in self.catalog_url:
logging.info("Network Request: %s", "Fetching {}".format(url))
self.catalog_raw.append(requests.get(url, headers=ClientMeta.swupdate))
self.catalog_data = [datum.text.encode('UTF-8') for datum in self.catalog_raw]
return self.catalog_data
def getosinstall(self):
# Load catalogs based on Py3/2 lib
if sys.version_info > (3, 0):
root = plistlib.loads(self.catalog_data)
else:
root = plistlib.readPlistFromString(self.catalog_data)
roots = list()
for index, datum in enumerate(self.catalog_data):
if sys.version_info > (3, 0):
# Ignore any missing/corrupted catalogs
try:
roots.append(plistlib.loads(datum))
except plistlib.InvalidFileException:
logging.warning("Catalog at {} corrupted or missing, contents won't be downloaded.".format(self.catalog_url[index]))
else:
roots.append(plistlib.readPlistFromString(datum))
# Iterate to find valid OSInstall packages
ospackages = []
products = root['Products']
for product in products:
if products.get(product, {}).get('ExtendedMetaInfo', {}).get('InstallAssistantPackageIdentifiers', {}).get('OSInstall', {}) == 'com.apple.mpkg.OSInstall':
ospackages.append(product)
ospackages = list()
for root in roots:
products = root['Products']
for product in products:
if products.get(product, {}).get('ExtendedMetaInfo', {}).get('InstallAssistantPackageIdentifiers', {}).get('OSInstall', {}) == 'com.apple.mpkg.OSInstall':
ospackages.append(product)
return ospackages
@ -107,32 +128,53 @@ class MacOSProduct:
@click.command()
@click.option('-o', '--output-dir', default="BaseSystem/", help="Target directory for package output.")
@click.option('-c', '--catalog-id', default="PublicRelease", help="Name of catalog.")
@click.option('-a', '--fetch-all', is_flag=True, help="Get all available macOS packages. Implies --package=\"__ALL__\", --catalog-id=\"__ALL__\", and --output-dir=\"SoftwareUpdate\". Conflicts with -l.")
@click.option('-l', '--latest', is_flag=True, help="Get latest available macOS package. Conflicts with -a.")
@click.option('-c', '--catalog-id', default="PublicRelease", help="Name of catalog. Specify \"__ALL__\" to attempt to fetch all catalogs.")
@click.option('-p', '--product-id', default="", help="Product ID (as seen in SoftwareUpdate).")
@click.option('-l', '--latest', is_flag=True, help="Get latest available macOS package.")
def fetchmacos(output_dir="BaseSystem/", catalog_id="PublicRelease", product_id="", latest=False):
@click.option('-k', '--package', default="BaseSystem", help="Package keyword (as seen in SoftwareUpdate). Specify \"__ALL__\" a package to download all packages. Defaults to BaseSystem for backwards compatibility.")
def fetchmacos(output_dir="BaseSystem", catalog_id="PublicRelease", product_id="", latest=False, fetch_all=False, package="BaseSystem"):
# Apply implicit options of --fetch-all
if fetch_all:
output_dir="SoftwareUpdate"
catalog_id="__ALL__"
package=None
# Get the remote catalog data
remote = SoftwareService(catalog_id)
catalog = remote.getcatalog()
catalogs = remote.getcatalogs()
# If latest is used, find the latest OSInstall package
if latest:
product_id = remote.getosinstall()[-1]
else:
if product_id == "":
print("You must provide a Product ID (or pass the -l flag) to continue.")
exit(1)
# Fetch the given Product ID
try:
product = MacOSProduct(catalog, product_id)
except KeyError:
print("Product ID {} could not be found.".format(product_id))
# Ensure there's no conflicting flags
if latest and fetch_all:
print("You can only provide ONE OF the -l or -a flags, NOT both.")
exit(1)
logging.info("Selected macOS Product: {}".format(product_id))
# If latest is used, find the latest OSInstall package
elif latest:
product_id = remote.getosinstall()[0][-1]
# If fetch_all is used, find ALL the OSInstall packages
elif fetch_all:
logging.info("Selected ALL macOS Products")
for catalog in catalogs:
for product in remote.getosinstall():
print("Downloading product: {}".format(product))
p = MacOSProduct(catalog, product)
p.fetchpackages(os.path.join(output_dir, product))
exit(0)
elif product_id:
# Fetch the given Product ID
try:
product = MacOSProduct(catalogs[0], product_id)
logging.info("Selected macOS Product: {}".format(product_id))
except KeyError:
print("Product ID could not be found: {}".format(product_id))
exit(1)
else:
print("You must provide a Product ID (or pass one of the -l or -a flags) to continue.")
exit(1)
# Download package to disk
product.fetchpackages(output_dir, keyword="BaseSystem")
product.fetchpackages(output_dir, keyword=package)
if __name__ == "__main__":
fetchmacos()