Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 32 additions & 31 deletions brigadier
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#!/usr/bin/env python
#!/usr/bin/env python3

import os
import sys
import subprocess
import urllib2
import urllib.request, urllib.error, urllib.parse
import plistlib
import re
import tempfile
Expand All @@ -14,7 +14,7 @@ import platform
import requests

from pprint import pprint
from urllib import urlretrieve
from urllib.request import urlretrieve
from xml.dom import minidom

VERSION = '0.2.6'
Expand All @@ -23,7 +23,7 @@ SUCATALOG_URL = 'https://swscan.apple.com/content/catalogs/others/index-11-10.15
SEVENZIP_URL = 'https://www.7-zip.org/a/7z2201-x64.msi'

def status(msg):
print "%s\n" % msg
print("%s\n" % msg)

def getCommandOutput(cmd):
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
Expand Down Expand Up @@ -118,9 +118,9 @@ def installBootcamp(msipath):
status("Install log output:")
with open(logpath, 'r') as logfd:
logdata = logfd.read()
print logdata.decode('utf-16')
print(logdata.decode('utf-16'))
postInstallConfig()

def main():
scriptdir = os.path.abspath(os.path.dirname(sys.argv[0]))

Expand All @@ -147,7 +147,7 @@ according to the post date.")

opts, args = o.parse_args()
if opts.version:
print VERSION
print(VERSION)
sys.exit(0)

if opts.install:
Expand Down Expand Up @@ -182,7 +182,7 @@ when running the installer out of 'system32'." % output_dir)
if len(models) > 1:
status("Using Mac models: %s." % ', '.join(models))
else:
status("Using Mac model: %s." % ', '.join(models))
status("Using Mac model: %s." % ', '.join(models))

for model in models:
sucatalog_url = SUCATALOG_URL
Expand All @@ -191,45 +191,46 @@ when running the installer out of 'system32'." % output_dir)
plist_path = os.path.join(scriptdir, 'brigadier.plist')
if os.path.isfile(plist_path):
try:
config_plist = plistlib.readPlist(plist_path)
with open(plist_path, 'rb') as f:
config_plist = plistlib.load(f)
except:
status("Config plist was found at %s but it could not be read. \
Verify that it is readable and is an XML formatted plist." % plist_path)
if config_plist:
if 'CatalogURL' in config_plist.keys():
if 'CatalogURL' in list(config_plist.keys()):
sucatalog_url = config_plist['CatalogURL']


urlfd = urllib2.urlopen(sucatalog_url)
urlfd = urllib.request.urlopen(sucatalog_url)
data = urlfd.read()
p = plistlib.readPlistFromString(data)
p = plistlib.loads(data)
allprods = p['Products']

# Get all Boot Camp ESD products
bc_prods = []
for (prod_id, prod_data) in allprods.items():
if 'ServerMetadataURL' in prod_data.keys():
for (prod_id, prod_data) in list(allprods.items()):
if 'ServerMetadataURL' in list(prod_data.keys()):
bc_match = re.search('BootCamp', prod_data['ServerMetadataURL'])
if bc_match:
bc_prods.append((prod_id, prod_data))
# Find the ESD(s) that applies to our model
pkg_data = []
re_model = "([a-zA-Z]{4,12}[1-9]{1,2}\,[1-6])"
for bc_prod in bc_prods:
if 'English' in bc_prod[1]['Distributions'].keys():
if 'English' in list(bc_prod[1]['Distributions'].keys()):
disturl = bc_prod[1]['Distributions']['English']
distfd = urllib2.urlopen(disturl)
dist_data = distfd.read()
distfd = urllib.request.urlopen(disturl)
dist_data = distfd.read().decode('utf-8')
if re.search(model, dist_data):
supported_models = []
pkg_data.append({bc_prod[0]: bc_prod[1]})
model_matches_in_dist = re.findall(re_model, dist_data)
for supported_model in model_matches_in_dist:
supported_models.append(supported_model)
status("Model supported in package distribution file at %s." % disturl)
status("Distribution %s supports the following models: %s." %
status("Distribution %s supports the following models: %s." %
(bc_prod[0], ", ".join(supported_models)))

# Ensure we have only one ESD
if len(pkg_data) == 0:
sys.exit("Couldn't find a Boot Camp ESD for the model %s in the given software update catalog." % model)
Expand All @@ -239,37 +240,37 @@ when running the installer out of 'system32'." % output_dir)
sys.exit("--product-id option is only applicable when multiple ESDs are found for a model.")
if len(pkg_data) > 1:
# sys.exit("There is more than one ESD product available for this model: %s. "
# "Automically selecting the one with the most recent PostDate.."
# "Automically selecting the one with the most recent PostDate.."
# % ", ".join([p.keys()[0] for p in pkg_data]))
print "There is more than one ESD product available for this model:"
print("There is more than one ESD product available for this model:")
# Init latest to be epoch start
latest_date = datetime.datetime.fromtimestamp(0)
chosen_product = None
for i, p in enumerate(pkg_data):
product = p.keys()[0]
product = list(p.keys())[0]
postdate = p[product].get('PostDate')
print "%s: PostDate %s" % (product, postdate)
print("%s: PostDate %s" % (product, postdate))
if postdate > latest_date:
latest_date = postdate
chosen_product = product

if opts.product_id:
if opts.product_id not in [k.keys()[0] for k in pkg_data]:
if opts.product_id not in [list(k.keys())[0] for k in pkg_data]:
sys.exit("Product specified with '--product-id %s' either doesn't exist "
"or was not found applicable to models: %s"
% (opts.product_id, ", ".join(models)))
chosen_product = opts.product_id
print "Selecting manually-chosen product %s." % chosen_product
print("Selecting manually-chosen product %s." % chosen_product)
else:
print "Selecting %s as it's the most recently posted." % chosen_product
print("Selecting %s as it's the most recently posted." % chosen_product)

for p in pkg_data:
if p.keys()[0] == chosen_product:
if list(p.keys())[0] == chosen_product:
selected_pkg = p
pkg_data = selected_pkg

pkg_id = pkg_data.keys()[0]
pkg_url = pkg_data.values()[0]['Packages'][0]['URL']
pkg_id = list(pkg_data.keys())[0]
pkg_url = list(pkg_data.values())[0]['Packages'][0]['URL']

# make a sub-dir in the output_dir here, named by product
landing_dir = os.path.join(output_dir, 'BootCamp-' + pkg_id)
Expand Down Expand Up @@ -364,13 +365,13 @@ when running the installer out of 'system32'." % output_dir)
shutil.move(os.path.join(arc_workdir, 'Library/Application Support/BootCamp/WindowsSupport.dmg'),
output_file)
subprocess.call(['7z','-o{}'.format(landing_dir),'x','WindowsSupport.dmg',])

status("Extracted to %s." % output_file)

if os.path.exists('/mnt/c/Windows/explorer.exe'):
subprocess.call(['/mnt/c/Windows/explorer.exe','.'])
else:
print("Platform not supported! ({})".format(platform.system()))
print(("Platform not supported! ({})".format(platform.system())))
pass

status("Done.")
Expand Down