diff --git a/Installomator.sh b/Installomator.sh index 6b4ec95..dd374a7 100755 --- a/Installomator.sh +++ b/Installomator.sh @@ -31,31 +31,31 @@ fi # # 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 -# 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) # 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 # # - targetDir: (optional) # Applications will be copied to this directory, remember to omit trailing '/' -# default value is '/Applications' - -targetDir="/Applications" - +# default value is '/Applications' for dmg and zip installations +# for pkgs default targetDir is "/" # todos: # TODO: add pkg support +# TODO: add zip support # TODO: check for running processes and either abort or prompt user # TODO: log version of installed software # TODO: notification when done # 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 gitusername=${1?:"no git user name"} gitreponame=${2?:"no git repo name"} @@ -89,13 +89,17 @@ case $identifier in ;; Firefox) downloadURL="https://download.mozilla.org/?product=firefox-latest&os=osx&lang=en-US" - dmgName="Firefox.dmg" + archiveName="Firefox.dmg" expectedTeamID="43AQ936H96" ;; WhatsApp) downloadURL="https://web.whatsapp.com/desktop/mac/files/WhatsApp.dmg" expectedTeamID="57T9237FN3" ;; + desktoppr) + downloadURL=$(downloadURLFromGit "scriptingosx" "desktoppr") + expectedTeamID="JME5BW3F3R" + ;; # these identifiers exist for testing brokenDownloadURL) @@ -120,14 +124,7 @@ case $identifier in ;; esac -if [ -z "$dmgName" ]; then - dmgName="${downloadURL##*/}" -fi - -if [ -z "$appName" ]; then - appName="${dmgName%%.*}.app" -fi - +# functions cleanupAndExit() { # $1 = exit code if [ "$DEBUG" -eq 0 ]; then # remove the temporary working directory when done @@ -145,6 +142,140 @@ cleanupAndExit() { # $1 = exit code 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 tmpDir=$(mktemp -d ) 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 -if [ -f "$dmgName" ] && [ "$DEBUG" -eq 1 ]; then - echo "$dmgName exists and DEBUG enabled, skipping download" +if [ -f "$archiveName" ] && [ "$DEBUG" -eq 1 ]; then + echo "$archiveName exists and DEBUG enabled, skipping download" else # download the dmg - echo "Downloading $downloadURL to $dmgName" - if ! curl --location --fail --silent "$downloadURL" -o "$dmgName"; then + echo "Downloading $downloadURL to $archiveName" + if ! curl --location --fail --silent "$downloadURL" -o "$archiveName"; then echo "error downloading $downloadURL" cleanupAndExit 2 fi fi -# mount the dmg -echo "Mounting $tmpDir/$dmgName" -# set -o pipefail -if ! dmgmount=$(hdiutil attach "$tmpDir/$dmgName" -nobrowse -readonly | tail -n 1 | cut -c 54- ); then - echo "Error mounting $tmpDir/$dmgName" - cleanupAndExit 3 -fi -echo "Mounted: $dmgmount" +case $type in + dmg) + installFromDMG + ;; + pkg) + installFromPKG + ;; + *) + 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