Skip to content

Instantly share code, notes, and snippets.

@sjha967
Forked from talkingmoose/MegaPKGr.zsh
Created December 10, 2020 14:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sjha967/41a0cc4d0da63be16f06b9e2f5912f21 to your computer and use it in GitHub Desktop.
Save sjha967/41a0cc4d0da63be16f06b9e2f5912f21 to your computer and use it in GitHub Desktop.
The pkgbuild binary and Jamf Composer don't support adding single files of 8 GB or more to a package. Some apps like Install macOS Big Sur.app include files larger than 8 GB in their bundles. This script will create a deployable PKG file from apps whose bundles include those large files.
#!/bin/zsh
:<<ABOUT_THIS_SCRIPT
-------------------------------------------------------------------------------
Written by:William Smith
Professional Services Engineer
Jamf
bill@talkingmoose.net
https://gist.github.com/e9ed319226c6da30dd633725e48a97b0
Originally posted: October 15, 2020
Updated: December 2, 2020
Purpose: Creates a deployable PKG file from an app whose app bundle
contains one or more files larger than the 8 GB limit supported by pkgbuild
or Jamf Composer.
Instructions:
1. Save the script to a file named MegaPKGr.zsh on your Mac.
2. If necessary, run 'chmod +x /path/to/MegaPKGr.zsh' to make it execu-
table.
3. To run the script, open Terminal and enter:
/path/to/MegaPKGr.zsh /path/to/large.app
Except where otherwise noted, this work is licensed under
http://creativecommons.org/licenses/by/4.0/
"If you try to save wisdom until the world is wise, Father,
the world will never have it."
-------------------------------------------------------------------------------
ABOUT_THIS_SCRIPT
function logmessage() {
echo -ne "$1\r"
/bin/sleep 1
}
function logresult() {
if [ $? = 0 ] ; then
echo "$1"
/bin/date "+%Y-%m-%d %H:%M:%S $1" >> "$logFile"
/bin/sleep 1
else
echo "$2"
/bin/date "+%Y-%m-%d %H:%M:%S $2" >> "$logFile"
echo "Aborting script"
/bin/date "+%Y-%m-%d %H:%M:%S Aborting script" >> "$logFile"
cleanup
exit 1
fi
}
function cleanup() {
logmessage "Removing temporary items..."
/bin/rm -Rf "$tempDirectory"
logresult "Succeeded removing temporary items" "Failed removing temporary items"
}
# need to run this script with elevated privileges
if [ $EUID -ne 0 ]; then
echo
echo "This script requires elevated privileges. Run it again with \"sudo\"."
echo
exit 0
fi
# define log file location
logFile="/Library/Logs/MegaPKGr.log"
# choose app for packaging
appPath="$1"
while [[ "$appPath" = "" ]]
do
echo
echo "Drag the app for packaging into this Terminal window and press return."
echo "To abort this script, press Control-C."
echo
read -p "App path: " appPath
done
app=$( /usr/bin/basename "$appPath" )
echo
# the time right now
startTime=$( /bin/date '+%s' )
# verify disk space needed to package app
appSize=$( /usr/bin/du -md 0 "$appPath" | /usr/bin/awk '{ print $1 }' )
logmessage "Size of \"$app\" in MB: $appSize"
availableSpace=$( /bin/df -g /System/Volumes/Data | /usr/bin/grep dev | /usr/bin/awk '{ print $4 }' )
logmessage "Available disk space: $availableSpace GB "
neededSpace=$(( appSize * 3 / 1024 ))
logmessage "Disk space required to build package: $neededSpace GB "
[ $availableSpace -gt $neededSpace ]
logresult "Disk has enough free space to build \"$app.pkg\"" "Disk does not have enough free space to build \"$app.pkg\""
echo "Log file is located in /Library/Logs/MegaPKGr.log"
echo
# create temporary working directory
logmessage "Creating temporary working directory..."
tempDirectory=$( /usr/bin/mktemp -d "/private/tmp/MegaPKGr.XXXXXX" )
logresult "Succeeded creating temporary working directory" "Failed creating temporary working directory"
# create dmg from the app to create a single file
logmessage "Creating disk image (DMG) archive of \"$app\"..."
/usr/bin/hdiutil create -quiet "$tempDirectory/$app.dmg" -ov -volname MegaPKGr -fs APFS -srcfolder "$appPath"
logresult "Succeeded creating DMG archive of $app" "Failed creating DMG archive of $app"
# create folder structure for pkgbuild
logmessage "Ceating pkgbuild ROOT directory..."
/bin/mkdir -p "$tempDirectory/ROOT/private/tmp/MegaPKGrFileParts" && cd "$tempDirectory/ROOT/private/tmp/MegaPKGrFileParts"
logresult "Succeeded creating pkgbuild ROOT directory" "Failed creating pkgbuild ROOT directory"
logmessage "Creating pkgbuild Scripts directory"
/bin/mkdir -p "$tempDirectory/Scripts"
logresult "Succeeded creating pkgbuild Scripts directory" "Failed creating pkgbuild Scripts directory"
# split archive file into 500 MB file chunks
logmessage "Creating 500 MB file chunks from archive file..."
/usr/bin/split -b 500m "$tempDirectory/$app.dmg"
logresult "Succeeded creating 500 MB file chunks from archive file" "Failed creating 500 MB file chunks from archive file"
# create postinstall script for pkgbuild
logmessage "Creating pkgbuild postinstall script..."
/bin/cat << 'EOF' > "$tempDirectory/Scripts/postinstall"
#!/bin/bash
function logresult() {
if [ $? = 0 ] ; then
echo "$1"
else
echo "$2"
exit 1
fi
}
function cleanup() {
/bin/rm -Rf "$tempDirectory/" "/private/tmp/MegaPKGr"*
logresult "[RESULT: $?] Succeeded removing temporary items" "[ERROR: $?] Failed removing temporary items"
}
# create temporary working directory
echo "Creating temporary working directory"
tempDirectory=$( /usr/bin/mktemp -d "/private/tmp/MegaPKGr.XXXXXX" )
logresult "[RESULT: $?] Succeeded creating temporary working directory" "[ERROR: $?] Failed creating temporary working directory"
# change directory to temporary working directory
echo "Changing directory to working directory '$tempDirectory'"
cd "$tempDirectory"
logresult "[RESULT: $?] Succeeded changing to temporary working directory" "[ERROR: $?] Failed changing to temporary working directory"
# recombine file parts
echo "Recombining file parts"
/bin/cat /private/tmp/MegaPKGrFileParts/x* > "$tempDirectory/MegaPKGrFileParts.dmg"
logresult "[RESULT: $?] Succeeded recombining MegaPKGrFileParts file parts" "[ERROR: $?] Failed recombining MegaPKGrFileParts file parts"
# copy the application to original location
echo "Extracting archived file"
# mounting recombined DMG
/usr/bin/hdiutil attach -nobrowse "$tempDirectory/MegaPKGrFileParts.dmg"
logresult "[RESULT: $?] Succeeded mounting DMG" "[ERROR: $?] Failed mounting DMG"
# dittoing DMG contents to local disk
/usr/bin/ditto -rsrc "/Volumes/MegaPKGr/" /Applications
logresult "[RESULT: $?] Succeeded dittoing files to specified location" "[ERROR: $?] Failed dittoing files to specified location"
# unmounting recombined DMG
/sbin/umount "/Volumes/MegaPKGr"
logresult "[RESULT: $?] Succeeded unmounting DMG" "[ERROR: $?] Failed unmounting DMG"
# delete temporary files
echo "Deleting temporary items"
cleanup
exit 0
EOF
/bin/chmod +x "$tempDirectory/Scripts/postinstall"
logresult "Succeeded creating pkgbuild postinstall script" "Failed creating pkgbuild postinstall script"
# create installer package
currentDirectory=$( /usr/bin/dirname "$0" )
logmessage "Creating package \"$app.pkg\"..."
/usr/bin/pkgbuild --quiet --identifier net.talkingmoose.MegaPKGr --version "1.0.0" --scripts "$tempDirectory/Scripts" --root "$tempDirectory/ROOT" "$currentDirectory/$app.pkg"
logresult "Succeeded creating package \"$app.pkg\" in the same folder as this script" "Failed creating package \"$app.pkg\" in the same folder as this script"
# remove temporary files
logmessage "Removing temporary items..."
cleanup
echo
# calculate and report script run time
stopTime=$( /bin/date '+%s' )
seconds=$(( $stopTime-$startTime ))
formattedTime=$( /bin/date -j -f "%s" "$seconds" '+%M minutes and %S seconds' )
logresult "Packaging time: $formattedTime"
echo
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment