Add SeedProgram xattr to Install macOS app; making a compressed read-only dmg is now the default

This commit is contained in:
Greg Neagle 2018-08-14 15:26:17 -07:00
parent aca77ebbf2
commit 314eca5f23

View File

@ -31,6 +31,7 @@ import plistlib
import subprocess import subprocess
import sys import sys
import urlparse import urlparse
import xattr
from xml.dom import minidom from xml.dom import minidom
from xml.parsers.expat import ExpatError from xml.parsers.expat import ExpatError
@ -40,15 +41,27 @@ DEFAULT_SUCATALOG = (
'index-10.13seed-10.13-10.12-10.11-10.10-10.9' 'index-10.13seed-10.13-10.12-10.11-10.10-10.9'
'-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz') '-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz')
SEED_CATALOGS_PLIST = (
'/System/Library/PrivateFrameworks/Seeding.framework/Versions/Current/'
'Resources/SeedCatalogs.plist'
)
def get_seeding_program(sucatalog_url):
'''Returns a seeding program name based on the sucatalog_url'''
try:
seed_catalogs = plistlib.readPlist(SEED_CATALOGS_PLIST)
for key, value in seed_catalogs.items():
if sucatalog_url == value:
return key
except (OSError, ExpatError, AttributeError, KeyError):
return None
def get_seed_catalog(): def get_seed_catalog():
'''Returns the developer seed sucatalog''' '''Returns the developer seed sucatalog'''
seed_catalogs_plist = (
'/System/Library/PrivateFrameworks/Seeding.framework/Versions/Current/'
'Resources/SeedCatalogs.plist'
)
try: try:
seed_catalogs = plistlib.readPlist(seed_catalogs_plist) seed_catalogs = plistlib.readPlist(SEED_CATALOGS_PLIST)
return seed_catalogs.get('DeveloperSeed', DEFAULT_SUCATALOG) return seed_catalogs.get('DeveloperSeed', DEFAULT_SUCATALOG)
except (OSError, ExpatError, AttributeError, KeyError): except (OSError, ExpatError, AttributeError, KeyError):
return DEFAULT_SUCATALOG return DEFAULT_SUCATALOG
@ -352,6 +365,15 @@ def replicate_product(catalog, product_id, workdir, ignore_cache=False):
exit(-1) exit(-1)
def find_installer_app(mountpoint):
'''Returns the path to the Install macOS app on the mountpoint'''
applications_dir = os.path.join(mountpoint, 'Applications')
for item in os.listdir(applications_dir):
if item.endswith('.app'):
return os.path.join(applications_dir, item)
return None
def main(): def main():
'''Do the main thing here''' '''Do the main thing here'''
if os.getuid() != 0: if os.getuid() != 0:
@ -369,7 +391,13 @@ def main():
'directory.') 'directory.')
parser.add_argument('--compress', action='store_true', parser.add_argument('--compress', action='store_true',
help='Output a read-only compressed disk image with ' help='Output a read-only compressed disk image with '
'the Install macOS app at the root.') 'the Install macOS app at the root. This is now the '
'default. Use --raw to get a read-write sparse image '
'with the app in the Applications directory.')
parser.add_argument('--raw', action='store_true',
help='Output a read-write sparse image '
'with the app in the Applications directory. Requires '
'less available disk space and is faster.')
parser.add_argument('--ignore-cache', action='store_true', parser.add_argument('--ignore-cache', action='store_true',
help='Ignore any previously cached files.') help='Ignore any previously cached files.')
args = parser.parse_args() args = parser.parse_args()
@ -431,22 +459,25 @@ def main():
print >> sys.stderr, 'Product installation failed.' print >> sys.stderr, 'Product installation failed.'
unmountdmg(mountpoint) unmountdmg(mountpoint)
exit(-1) exit(-1)
# add the seeding program xattr to the app if applicable
seeding_program = get_seeding_program(args.catalogurl)
if seeding_program:
installer_app = find_installer_app(mountpoint)
if installer_app:
xattr.setxattr(installer_app, 'SeedProgram', seeding_program)
print 'Product downloaded and installed to %s' % sparse_diskimage_path print 'Product downloaded and installed to %s' % sparse_diskimage_path
if not args.compress: if args.raw:
unmountdmg(mountpoint) unmountdmg(mountpoint)
else: else:
# if --compress option given, create a r/o compressed diskimage # if --raw option not given, create a r/o compressed diskimage
# containing the Install macOS app # containing the Install macOS app
compressed_diskimagepath = os.path.join( compressed_diskimagepath = os.path.join(
args.workdir, volname + '.dmg') args.workdir, volname + '.dmg')
if os.path.exists(compressed_diskimagepath): if os.path.exists(compressed_diskimagepath):
os.unlink(compressed_diskimagepath) os.unlink(compressed_diskimagepath)
applications_dir = os.path.join(mountpoint, 'Applications') app_path = find_installer_app(mountpoint)
for item in os.listdir(applications_dir): if app_path:
if item.endswith('.app'): make_compressed_dmg(app_path, compressed_diskimagepath)
app_path = os.path.join(applications_dir, item)
make_compressed_dmg(app_path, compressed_diskimagepath)
break
# unmount sparseimage # unmount sparseimage
unmountdmg(mountpoint) unmountdmg(mountpoint)
# delete sparseimage since we don't need it any longer # delete sparseimage since we don't need it any longer