mirror of
https://github.com/mtan93/Installomator.git
synced 2026-03-08 05:31:53 +00:00
first "working" implementation of pkg support
This commit is contained in:
245
Installomator.sh
245
Installomator.sh
@@ -31,31 +31,31 @@ fi
|
|||||||
#
|
#
|
||||||
# the team ID is the ten-digit ID at the end of the line starting with 'origin='
|
# the team ID is the ten-digit ID at the end of the line starting with 'origin='
|
||||||
#
|
#
|
||||||
# - dmgName: (optional)
|
# - archiveName: (optional)
|
||||||
# The name of the downloaded dmg
|
# The name of the downloaded dmg
|
||||||
# When not given the dmgName is derived from the last part of the downloadURL
|
# When not given the archiveName is derived from the last part of the downloadURL
|
||||||
#
|
#
|
||||||
# - appName: (optional)
|
# - appName: (optional)
|
||||||
# file name of the app bundle in the dmg to verify and copy (include .app)
|
# file name of the app bundle in the dmg to verify and copy (include .app)
|
||||||
# When not given, the App name is derived from the dmgName by removing the extension
|
# When not given, the App name is derived from the archiveName by removing the extension
|
||||||
# and adding .app
|
# and adding .app
|
||||||
#
|
#
|
||||||
# - targetDir: (optional)
|
# - targetDir: (optional)
|
||||||
# Applications will be copied to this directory, remember to omit trailing '/'
|
# Applications will be copied to this directory, remember to omit trailing '/'
|
||||||
# default value is '/Applications'
|
# default value is '/Applications' for dmg and zip installations
|
||||||
|
# for pkgs default targetDir is "/"
|
||||||
targetDir="/Applications"
|
|
||||||
|
|
||||||
|
|
||||||
# todos:
|
# todos:
|
||||||
|
|
||||||
# TODO: add pkg support
|
# TODO: add pkg support
|
||||||
|
# TODO: add zip support
|
||||||
# TODO: check for running processes and either abort or prompt user
|
# TODO: check for running processes and either abort or prompt user
|
||||||
# TODO: log version of installed software
|
# TODO: log version of installed software
|
||||||
# TODO: notification when done
|
# TODO: notification when done
|
||||||
|
|
||||||
# functions to help with getting info
|
# functions to help with getting info
|
||||||
|
|
||||||
|
# will get the latest release download from a github repo
|
||||||
downloadURLFromGit() { # $1 git user name, $2 git repo name
|
downloadURLFromGit() { # $1 git user name, $2 git repo name
|
||||||
gitusername=${1?:"no git user name"}
|
gitusername=${1?:"no git user name"}
|
||||||
gitreponame=${2?:"no git repo name"}
|
gitreponame=${2?:"no git repo name"}
|
||||||
@@ -89,13 +89,17 @@ case $identifier in
|
|||||||
;;
|
;;
|
||||||
Firefox)
|
Firefox)
|
||||||
downloadURL="https://download.mozilla.org/?product=firefox-latest&os=osx&lang=en-US"
|
downloadURL="https://download.mozilla.org/?product=firefox-latest&os=osx&lang=en-US"
|
||||||
dmgName="Firefox.dmg"
|
archiveName="Firefox.dmg"
|
||||||
expectedTeamID="43AQ936H96"
|
expectedTeamID="43AQ936H96"
|
||||||
;;
|
;;
|
||||||
WhatsApp)
|
WhatsApp)
|
||||||
downloadURL="https://web.whatsapp.com/desktop/mac/files/WhatsApp.dmg"
|
downloadURL="https://web.whatsapp.com/desktop/mac/files/WhatsApp.dmg"
|
||||||
expectedTeamID="57T9237FN3"
|
expectedTeamID="57T9237FN3"
|
||||||
;;
|
;;
|
||||||
|
desktoppr)
|
||||||
|
downloadURL=$(downloadURLFromGit "scriptingosx" "desktoppr")
|
||||||
|
expectedTeamID="JME5BW3F3R"
|
||||||
|
;;
|
||||||
|
|
||||||
# these identifiers exist for testing
|
# these identifiers exist for testing
|
||||||
brokenDownloadURL)
|
brokenDownloadURL)
|
||||||
@@ -120,14 +124,7 @@ case $identifier in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [ -z "$dmgName" ]; then
|
# functions
|
||||||
dmgName="${downloadURL##*/}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$appName" ]; then
|
|
||||||
appName="${dmgName%%.*}.app"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cleanupAndExit() { # $1 = exit code
|
cleanupAndExit() { # $1 = exit code
|
||||||
if [ "$DEBUG" -eq 0 ]; then
|
if [ "$DEBUG" -eq 0 ]; then
|
||||||
# remove the temporary working directory when done
|
# remove the temporary working directory when done
|
||||||
@@ -145,6 +142,140 @@ cleanupAndExit() { # $1 = exit code
|
|||||||
exit "$1"
|
exit "$1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
installFromDMG() {
|
||||||
|
# mount the dmg
|
||||||
|
echo "Mounting $tmpDir/$archiveName"
|
||||||
|
# set -o pipefail
|
||||||
|
if ! dmgmount=$(hdiutil attach "$tmpDir/$archiveName" -nobrowse -readonly | tail -n 1 | cut -c 54- ); then
|
||||||
|
echo "Error mounting $tmpDir/$archiveName"
|
||||||
|
cleanupAndExit 3
|
||||||
|
fi
|
||||||
|
echo "Mounted: $dmgmount"
|
||||||
|
|
||||||
|
# check if app exists
|
||||||
|
if [ ! -e "$dmgmount/$appName" ]; then
|
||||||
|
echo "could not find: $dmgmount/$appName"
|
||||||
|
cleanupAndExit 8
|
||||||
|
fi
|
||||||
|
|
||||||
|
# verify with spctl
|
||||||
|
echo "Verifying: $dmgmount/$appName"
|
||||||
|
if ! teamID=$(spctl -a -vv "$dmgmount/$appName" 2>&1 | awk '/origin=/ {print $NF }' ); then
|
||||||
|
echo "Error verifying $dmgmount/$appName"
|
||||||
|
cleanupAndExit 4
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Team ID: $teamID (expected: $expectedTeamID )"
|
||||||
|
|
||||||
|
if [ "($expectedTeamID)" != "$teamID" ]; then
|
||||||
|
echo "Team IDs do not match!"
|
||||||
|
cleanupAndExit 5
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check for root
|
||||||
|
if [ "$(whoami)" != "root" ]; then
|
||||||
|
# not running as root
|
||||||
|
if [ "$DEBUG" -eq 0 ]; then
|
||||||
|
echo "not running as root, exiting"
|
||||||
|
cleanupAndExit 6
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "DEBUG enabled, skipping copy and chown steps"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# remove existing application
|
||||||
|
if [ -e "$targetDir/$appName" ]; then
|
||||||
|
echo "Removing existing $targetDir/$appName"
|
||||||
|
rm -Rf "$targetDir/$appName"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# copy app to /Applications
|
||||||
|
echo "Copy $dmgmount/$appName to $targetDir"
|
||||||
|
if ! ditto "$dmgmount/$appName" "$targetDir"; then
|
||||||
|
echo "Error while copying!"
|
||||||
|
cleanupAndExit 7
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# set ownership to current user
|
||||||
|
currentUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }' )
|
||||||
|
if [ -n "$currentUser" ]; then
|
||||||
|
echo "Changing owner to $currentUser"
|
||||||
|
chown -R "$currentUser" "$targetDir/$appName"
|
||||||
|
else
|
||||||
|
echo "No user logged in, not changing user"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
installFromPKG() {
|
||||||
|
# verify with spctl
|
||||||
|
echo "Verifying: $archiveName"
|
||||||
|
if ! teamID=$(spctl -a -vv -t install "$archiveName" 2>&1 | awk '/origin=/ {print $NF }' ); then
|
||||||
|
echo "Error verifying $archiveName"
|
||||||
|
cleanupAndExit 4
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Team ID: $teamID (expected: $expectedTeamID )"
|
||||||
|
|
||||||
|
if [ "($expectedTeamID)" != "$teamID" ]; then
|
||||||
|
echo "Team IDs do not match!"
|
||||||
|
cleanupAndExit 5
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check for root
|
||||||
|
if [ "$(whoami)" != "root" ]; then
|
||||||
|
# not running as root
|
||||||
|
if [ "$DEBUG" -eq 0 ]; then
|
||||||
|
echo "not running as root, exiting"
|
||||||
|
cleanupAndExit 6
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "DEBUG enabled, skipping installation"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# install pkg
|
||||||
|
echo "Installing $archiveName to $targetDir"
|
||||||
|
if ! installer -pkg "$archiveName" -tgt "$targetDir" ; then
|
||||||
|
echo "error installing $archiveName"
|
||||||
|
cleanupAndExit 9
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# main
|
||||||
|
|
||||||
|
# extract info from data
|
||||||
|
if [ -z "$archiveName" ]; then
|
||||||
|
# when not given use last element of URL
|
||||||
|
archiveName="${downloadURL##*/}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$type" ]; then
|
||||||
|
# when not given use extension of archiveName
|
||||||
|
type="${archiveName##*.}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$appName" ]; then
|
||||||
|
# when not given derive from archiveName
|
||||||
|
appName="${archiveName%.*}.app"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$targetDir" ]; then
|
||||||
|
case $type in
|
||||||
|
dmg)
|
||||||
|
targetDir="/Applications"
|
||||||
|
;;
|
||||||
|
pkg)
|
||||||
|
targetDir="/"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Cannot handle type $type"
|
||||||
|
cleanupAndExit 99
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
# create temporary working directory
|
# create temporary working directory
|
||||||
tmpDir=$(mktemp -d )
|
tmpDir=$(mktemp -d )
|
||||||
if [ "$DEBUG" -eq 1 ]; then
|
if [ "$DEBUG" -eq 1 ]; then
|
||||||
@@ -162,80 +293,30 @@ fi
|
|||||||
|
|
||||||
# TODO: when user is logged in, and app is running, prompt user to quit app
|
# TODO: when user is logged in, and app is running, prompt user to quit app
|
||||||
|
|
||||||
if [ -f "$dmgName" ] && [ "$DEBUG" -eq 1 ]; then
|
if [ -f "$archiveName" ] && [ "$DEBUG" -eq 1 ]; then
|
||||||
echo "$dmgName exists and DEBUG enabled, skipping download"
|
echo "$archiveName exists and DEBUG enabled, skipping download"
|
||||||
else
|
else
|
||||||
# download the dmg
|
# download the dmg
|
||||||
echo "Downloading $downloadURL to $dmgName"
|
echo "Downloading $downloadURL to $archiveName"
|
||||||
if ! curl --location --fail --silent "$downloadURL" -o "$dmgName"; then
|
if ! curl --location --fail --silent "$downloadURL" -o "$archiveName"; then
|
||||||
echo "error downloading $downloadURL"
|
echo "error downloading $downloadURL"
|
||||||
cleanupAndExit 2
|
cleanupAndExit 2
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# mount the dmg
|
case $type in
|
||||||
echo "Mounting $tmpDir/$dmgName"
|
dmg)
|
||||||
# set -o pipefail
|
installFromDMG
|
||||||
if ! dmgmount=$(hdiutil attach "$tmpDir/$dmgName" -nobrowse -readonly | tail -n 1 | cut -c 54- ); then
|
;;
|
||||||
echo "Error mounting $tmpDir/$dmgName"
|
pkg)
|
||||||
cleanupAndExit 3
|
installFromPKG
|
||||||
fi
|
;;
|
||||||
echo "Mounted: $dmgmount"
|
*)
|
||||||
|
echo "Cannot handle type $type"
|
||||||
|
cleanupAndExit 99
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# check if app exists
|
|
||||||
if [ ! -e "$dmgmount/$appName" ]; then
|
|
||||||
echo "could not find: $dmgmount/$appName"
|
|
||||||
cleanupAndExit 8
|
|
||||||
fi
|
|
||||||
|
|
||||||
# verify with spctl
|
|
||||||
echo "Verifying: $dmgmount/$appName"
|
|
||||||
if ! teamID=$(spctl -a -vv "$dmgmount/$appName" 2>&1 | awk '/origin=/ {print $NF }' ); then
|
|
||||||
echo "Error verifying $dmgmount/$appName"
|
|
||||||
cleanupAndExit 4
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Team ID: $teamID (expected: $expectedTeamID )"
|
|
||||||
|
|
||||||
if [ "($expectedTeamID)" != "$teamID" ]; then
|
|
||||||
echo "Team IDs do not match!"
|
|
||||||
cleanupAndExit 5
|
|
||||||
fi
|
|
||||||
|
|
||||||
# check for root
|
|
||||||
if [ "$(whoami)" != "root" ]; then
|
|
||||||
# not running as root
|
|
||||||
if [ "$DEBUG" -eq 0 ]; then
|
|
||||||
echo "not running as root, exiting"
|
|
||||||
cleanupAndExit 6
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "DEBUG enabled, skipping copy and chown steps"
|
|
||||||
cleanupAndExit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# remove existing application
|
|
||||||
if [ -e "$targetDir/$appName" ]; then
|
|
||||||
echo "Removing existing $targetDir/$appName"
|
|
||||||
rm -Rf "$targetDir/$appName"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# copy app to /Applications
|
|
||||||
echo "Copy $dmgmount/$appName to $targetDir"
|
|
||||||
if ! ditto "$dmgmount/$appName" "$targetDir"; then
|
|
||||||
echo "Error while copying!"
|
|
||||||
cleanupAndExit 7
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
# set ownership to current user
|
|
||||||
currentUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }' )
|
|
||||||
if [ -n "$currentUser" ]; then
|
|
||||||
echo "Changing owner to $currentUser"
|
|
||||||
chown -R "$currentUser" "$targetDir/$appName"
|
|
||||||
else
|
|
||||||
echo "No user logged in, not changing user"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# TODO: notify when done
|
# TODO: notify when done
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user