diff --git a/README.md b/README.md index 38ab62e..f98b1d3 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ Some scripts that might be of use to macOS admins. Might be related to Munki; might not. -These are currently only supported using Apple's Python on macOS. There is no support for running these on Windows or Linux. +These are only supported on macOS. There is no support for running these on Windows or Linux. -In macOS 12.3, Apple will be removing its Python 2.7 install. You'll need to provide your own Python to use these scripts. You may also need to install additional Python modules. +In macOS 12.3, Apple stopped providung Python as part of macOS. You'll need to provide your own Python to use these scripts. You may also need to install additional Python modules. #### getmacosipsws.py @@ -39,7 +39,7 @@ Product installation failed. Use a compatible Mac or select a different build compatible with your current hardware and try again. You may also have success running the script in a VM; the InstallationCheck script in versions of the macOS installer to date skips the checks (and returns success) when run on a VM. ##### Important note for Catalina+ -Catalina privacy protections might interfere with the operation of this tool if you run it from ~/Desktop, ~/Documents, ~/Downloads or other directories protected in Catalina. Consider using /Users/Shared (or subdirectory) as the "working space" for this tool. +macOS privacy protections might interfere with the operation of this tool if you run it from ~/Desktop, ~/Documents, ~/Downloads or other directories protected in macOS Catalina or later. Consider using /Users/Shared (or subdirectory) as the "working space" for this tool. ##### Alternate implementations diff --git a/installinstallmacos.py b/installinstallmacos.py index 3e2eb5a..3897c9a 100755 --- a/installinstallmacos.py +++ b/installinstallmacos.py @@ -105,6 +105,18 @@ DEFAULT_SUCATALOGS = { "index-16seed-16-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9" "-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog" ), + "22": "https://swscan.apple.com/content/catalogs/others/" + "index-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9" + "-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog", + "23": "https://swscan.apple.com/content/catalogs/others/" + "index-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9" + "-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog", + "24": "https://swscan.apple.com/content/catalogs/others/" + "index-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9" + "-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog", + "25": "https://swscan.apple.com/content/catalogs/others/" + "index-26-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9" + "-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog", } SEED_CATALOGS_PLIST = ( @@ -285,11 +297,12 @@ def get_default_catalog(darwin_major=None): def make_sparse_image(volume_name, output_path): """Make a sparse disk image we can install a product to""" + # note: for macOS 26 Tahoe we needed to increase the size cmd = [ "/usr/bin/hdiutil", "create", "-size", - "16g", + "20g", "-fs", "HFS+", "-volname", @@ -399,7 +412,12 @@ def install_product(dist_path, target_vol): # set CM_BUILD env var to make Installer bypass eligibilty checks # when installing packages (for machine-specific OS builds) os.environ["CM_BUILD"] = "CM_BUILD" - cmd = ["/usr/sbin/installer", "-pkg", dist_path, "-target", target_vol] + # cmd = ['/usr/sbin/installer', '-pkg', dist_path, '-target', target_vol] + # a hack to work around a change in macOS 15.6+ since installing a .dist + # file no longer works + dist_dir = os.path.dirname(dist_path) + install_asst_pkg = os.path.join(dist_dir, "InstallAssistant.pkg") + cmd = ["/usr/sbin/installer", "-pkg", install_asst_pkg, "-target", target_vol] try: subprocess.check_call(cmd) except subprocess.CalledProcessError as err: @@ -1379,7 +1397,9 @@ def main(): % seeding_program ) xattr.setxattr( - installer_app, "SeedProgram", seeding_program.encode() + installer_app, + "SeedProgram", + seeding_program.encode("UTF-8").encode(), ) print("Product downloaded and installed to %s" % sparse_diskimage_path) if args.raw: diff --git a/munki_bundle_pkg_finder.py b/munki_bundle_pkg_finder.py new file mode 100755 index 0000000..3538774 --- /dev/null +++ b/munki_bundle_pkg_finder.py @@ -0,0 +1,62 @@ +#!/usr/local/munki/munki-python + +import os +import plistlib +import sys + +sys.path.append("/usr/local/munki") + +from munkilib import dmgutils +from munkilib import pkgutils + +if len(sys.argv) != 2: + print('Need exactly one parameter: path to a munki repo!', file=sys.stderr) + sys.exit(-1) + +repo_path = sys.argv[1] + +all_catalog = os.path.join(repo_path, "catalogs/all") + +with open(all_catalog, mode="rb") as FILE: + all_items = plistlib.load(FILE) + +dmg_items = [{"name": item["name"], + "version": item["version"], + "location": item["installer_item_location"], + "package_path": item.get("package_path", "")} + for item in all_items + if item.get("installer_item_location", "").endswith(".dmg") and + item.get("installer_type") is None] + +items_with_bundle_style_pkgs = [] +for item in dmg_items: + full_path = os.path.join(repo_path, "pkgs", item["location"]) + print("Checking %s..." % full_path) + mountpoints = dmgutils.mountdmg(full_path) + if mountpoints: + pkg_path = item["package_path"] + if pkg_path: + itempath = os.path.join(mountpoints[0], pkg_path) + if os.path.isdir(itempath): + print("***** %s--%s has a bundle-style pkg" + % (item["name"], item["version"])) + items_with_bundle_style_pkgs.append(item) + else: + for file_item in os.listdir(mountpoints[0]): + if pkgutils.hasValidInstallerItemExt(file_item): + itempath = os.path.join(mountpoints[0], file_item) + if os.path.isdir(itempath): + print("***** %s--%s has a bundle-style pkg" + % (item["name"], item["version"])) + items_with_bundle_style_pkgs.append(item) + break + dmgutils.unmountdmg(mountpoints[0]) + else: + print("No filesystems mounted from %s" % full_path) + continue + +print("Found %s items with bundle-style pkgs." + % len(items_with_bundle_style_pkgs)) +for item in sorted(items_with_bundle_style_pkgs, key=lambda d: d["name"]): + print("%s--%s"% (item["name"], item["version"])) + print(" %s" % item["location"])