JAL-4428 sign_dmg.sh with bells on
authorBen Soares <b.soares@dundee.ac.uk>
Fri, 16 Aug 2024 17:36:32 +0000 (18:36 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Fri, 16 Aug 2024 17:36:32 +0000 (18:36 +0100)
utils/osx_signing/sign_dmg.sh

index 1b3973c..dd98944 100755 (executable)
-#!/bin/bash
+#!/usr/bin/env bash
 
-if [[ "$GITDIR" == "" ]]; then
-    GITDIR=~/uod-development/jalview-builds/git/jalview
-fi;
+# These are the defaults if neither env vars or command line option are set
+[ -z $GITDIR ] && GITDIR="~/uod-development/jalview-builds/git/jalview"
+[ -z $DEVELOPERID ] && DEVELOPERID="Developer ID"
+[ -z $JVER ] && JVER="8"
+TMP="/tmp"
+TMPDMG="signingDMG"
+TESTARCH="|x64|aarch64|"
+YES=0
+CLEANUP=0
+GITENTITLEMENTSPATH="utils/osx_signing/entitlements.txt"
+NOCODESIGNING=0
+NOVOLUMEICON=0
+VOLUMEICONPATH="utils/channels/release/images/jalview-VolumeIcon.icns"
+DEFAULTVOLUMEICONFILE=".VolumeIcon.icns"
 
-if [[ "$DEVELOPERID" == "" ]]; then
-    DEVELOPERID="Developer ID"
-fi;
+usage() {
+  echo "Usage: $( basename $0 ) [-h] [[-g gitdir] | [-e entfile]] [-d devid] [[-a appname] [-v appver ] [-j arch] [-w jver] | [-i dmgfile]] [-O] [-o outputdmg] [-t tmpdir] [-s signingdmg] [-S] [-z icnsfile] [-Z] [-y] [-C]"
+  echo "  "
+  echo "  This script is used in the signing process of DMG disk image files for macOS."
+  echo "  Either -g GITDIR or -e ENTFILE should be given."
+  echo "  Either -i DMGFILE or all of -a APPNAME -v APPVER -j ARCH -w JVER should be given."
+  echo "  Environment variables will be used if set and no options given."
+  echo "  Precedence is in the order of command line option, environment variable (where indicated), default (where indicated)."
+  echo "  "
+  echo "  -h             Show help"
+  echo "  -g gitdir      Use git directory gitdir (also uses GITDIR env variable, default '$ARG_G')"
+  echo "  -e entfile     Use entitlements file entfile (defaults to 'GITDIR/${GITENTITLEMENTSPATH}')"
+  echo "  -d devid       Use the Developer ID devid (also uses DEVELOPERID env variable, default '$ARG_D')."
+  echo "  -a appname     Use the Application name appname (defaults to the first .app name found on DMG volume)."
+  echo "  -v appver      Assume application version appver (also uses APPVER env variable. No default)."
+  echo "  -j arch        Use the JVM architecture arch (also uses ARCH env variable. No default, should be one of${TESTARCH//|/ })."
+  echo "  -w jver        Assume java version jver (also uses JVER env variable. Defaults to '1.8')."
+  echo "  -i dmgfile     Sign DMGFILE (also uses DMGFILE env variable. Defaults to a combination of GITDIR, APPNAME, APPVER, ARCH and JVER)."
+  echo "  -t tmpdir      Use temp directory tmpdir (default '/tmp')."
+  echo "  -s signingdmg  Use signingdmg as the temporary signing folder name (default 'signingDMG')."
+  echo "  -S             Don't perform any code signing."
+  echo "  -z icnsfile    Use icnsfile as the volume icon file (defaults to using existing '$DEFAULTVOLUMEICONFILE' file or 'GITDIR/${VOLUMEICONPATH}'."
+  echo "  -Z             Don't set the volume icon, even if it already exists."
+  echo "  -O             Overwrite the output DMG file if it already exists."
+  echo "  -o outputdmg   Output DMG file (defaults to existing dmgfile in a 'signed' sub-directory)."
+  echo "  -y             Assume 'yes' to all confirmation requests."
+  echo "  -C             Cleanup temporary folders for the given dmgfile (Prevents all other activities. Cleanup can be narrowed down with either -i or some/all of -a -v -j -w."
+}
 
-if [[ "$TMPDMG" == "" ]]; then
-    TMPDMG="signingDMG"
-fi;
+while getopts "hg:e:d:a:v:j:w:i:t:s:Sz:ZyCOo:" opt; do
+  case ${opt} in
+    h)
+      usage
+      exit
+      ;;
+    g)
+      GITDIR="${OPTARG}"
+      ;;
+    e)
+      ENTITLEMENTSFILE="${OPTARG}"
+      ;;
+    d)
+      DEVELOPERID="${OPTARG}"
+      ;;
+    a)
+      APPNAME="${OPTARG}"
+      ;;
+    v)
+      APPVER="${OPTARG}"
+      ;;
+    j)
+      ARCH="${OPTARG}"
+      ;;
+    w)
+      JVER="${OPTARG}"
+      WJVER="$JVER"
+      ;;
+    i)
+      DMGFILE="${OPTARG}"
+      ;;
+    o)
+      OUTPUTDMGFILE="${OPTARG}"
+      ;;
+    O)
+      OVERWRITE=1
+      ;;
+    t)
+      TMP="${OPTARG}"
+      ;;
+    s)
+      TMPDMG="${OPTARG}"
+      ;;
+    S)
+      NOCODESIGNING=1
+      ;;
+    z)
+      VOLUMEICON="${OPTARG}"
+      ;;
+    Z)
+      NOVOLUMEICON=1
+      ;;
+    y)
+      YES=1
+      ;;
+    C)
+      CLEANUP=1
+      ;;
+    *)
+      echo "Unrecognised option. Run with -h for help."
+      exit 1
+      ;;
+  esac
+done
 
-echo APPNAME $APPNAME like Jalview Test
-echo doing ARCH $ARCH
-echo using entitlements from $GITDIR
-echo using key $DEVELOPERID
+if [ "$CLEANUP" != 1 ]; then
+    # Now check GITDIR, ENTITLEMENTSFILE, DEVELOPERID, APPNAME, APPVER, ARCH, JVER, DMGFILE, TMP, TMPDMG
 
-FAPPNAME="${APPNAME/ /\\ }"
-FAPPNAMEESC="${APPNAME/ /\\\\\\ }"
-FWAPP="${APPNAME/ [A-Za-z]*/}"
-ARCHNAME="${APPNAME// /_}-${APPVER//\./_}-macos-$ARCH-java_$JVER"
-DMGNAME="${APPNAME/ /_}-${APPVER//\./_}-macos-$ARCH-java_$JVER.dmg"
-VOLNAME="${APPNAME// /_}\\ Installer\\ \\(${APPVER//\./_}\\ $ARCH\\ $JVER\\)"
-VLNAME="${APPNAME// /_} Installer (${APPVER//\./_} $ARCH $JVER)"
-BORINGVLNAME="${APPNAME} Installer"
+    # check entitlements setting and file exists
+    if [ -z "$ENTITLEMENTSFILE" ]; then
+        ENTITLEMENTSFILE="${GITDIR}/${GITENTITLEMENTSPATH}"
+    fi
+    if [ -z "$ENTITLEMENTSFILE" ]; then
+        echo "Must set an entitlements file with -e entfile or -g GITDIR (or with GITDIR env variable)."
+        echo ""
+        usage
+        exit 2
+    fi
+    if [ ! -e "$ENTITLEMENTSFILE" ]; then
+        echo "Entitlements file '$ENTITLEMENTSFILE' doesn't exist"
+        exit 3
+    fi
 
+    # check developer id
+    if [ -z "$DEVELOPERID" ]; then
+        echo "Must set a Developer ID with -d DEVELOPERID (or with env variable)."
+        echo ""
+        usage
+        exit 4
+    fi
 
+    # check ARCH is set and valid
+    if [ ! -z "$ARCH" -a "${TESTARCH/|$ARCH|/}" = "$TESTARCH" ]; then # not a valid arch
+        echo "ARCH must be one of${TESTARCH//|/ }. Set with -a ARCH (or with env variable)."
+        echo ""
+        usage
+        exit 5
+    fi
 
-echo "will mount $DMGNAME as $VOLNAME"
-if [[ -d $TMPDMG ]]; then
-       echo "'$TMPDMG' is in the way. Please delete it or set TMPDMG"
-       exit 1;
+    # check VOLUMEICON
+    USEVOLUMEICON=0
+    if [ ! -z "$VOLUMEICON" ]; then
+        if [ ! -e "$VOLUMEICON" ]; then
+            echo "Volume icon is set to '$VOLUMEICON' but it does not exist.  Use -Z to NOT set a volume icon."
+            exit 6
+        fi
+        USEVOLUMEICON=1
+    else
+        VOLUMEICON="${GITDIR}/${VOLUMEICONPATH}"
+        if [ ! -e "$VOLUMEICON" ]; then
+            VOLUMEICON=""
+        fi
+        USEVOLUMEICON=1
+    fi
+
+    # check DMGFILE or alternative component args, set DMGFILE and check it exists
+    if [ -z "$DMGFILE" -a \( -z "$APPNAME" -o -z "$APPVER" -o -z "$ARCH" -o -z "$JVER" \) ]; then
+        echo "Must set either -i DMGFILE or all of -a APPNAME -v APPVER -j ARCH -w JVER (or with env variables)."
+        echo ""
+        usage
+        exit 7
+    fi
+fi
+
+if [ -z "$DMGFILE" ]; then
+  if [ "$CLEANUP" = 1 ]; then
+    # we can use wildcards for cleanup
+    [ -z "$APPNAME" ] && WAPPNAME="jalview*" || WAPPNAME="$APPNAME"
+    [ -z "$APPVER" ] && WAPPVER="*" || WAPPVER="$APPVER"
+    [ -z "$ARCH" ] && WARCH="*" || WARCH="$ARCH"
+    [ -z "$WJVER" ] && WJVER="*" # JVER is never ""
+    DMGNAME="${WAPPNAME// /_}-${WAPPVER//\./_}-macos-${WARCH}-java_${WJVER}.dmg"
+    DMGFILE="/tmp/fictitious.dmg"
+  else
+    DMGNAME="${APPNAME// /_}-${APPVER//\./_}-macos-${ARCH}-java_${JVER}.dmg"
+    OLDJVER=$([ "$JVER" -lt 9 ] && echo "1.${JVER}" || echo "${JVER}" )
+    DMGFILE="${GITDIR}/install4j/${OLDJVER}/${DMGNAME}"
+  fi
+else
+  DMGNAME="$( basename "$DMGFILE" )"
+fi
+
+DMGNAMELC=$(echo "${DMGNAME//[ .]/_}" | tr '[:upper:]' '[:lower:]')
+
+if [ -z "$DMGFILE" ]; then
+  echo "Must set a DMG disk image file with -i."
+  echo ""
+  usage
+  exit 8
+fi
+
+if [ "$CLEANUP" = 1 ]; then
+  TO_REMOVE=""
+  TEMPBASE="${TMP}/${DMGNAMELC}"
+else
+  if [ ! -e "$DMGFILE" ]; then
+    echo "DMG disk image file '$DMGFILE' doesn't exist"
+    exit 9
+  fi
+  TEMPDIR=$(mktemp -d -p "${TMP}" -t "${DMGNAMELC}")
+  DMGDIR=$(dirname "$DMGFILE")
+fi
+
+if [ "$CLEANUP" = 1 ]; then
+  echo "* -- Removing leftover temporary folders for DMG file '$DMGNAME' matching '${TEMPBASE}.*' ."
+  TO_REMOVE=$( ls -1d $TEMPBASE.* 2> /dev/null )
+
+  if [ -z "$TO_REMOVE" ]; then
+    echo "* Nothing to remove. Exiting."
+    exit
+  fi
+
+  while IFS= read -r REMOVE; do
+    echo "*    + will remove '${REMOVE}'"
+  done <<< "$TO_REMOVE"
+else
+  echo "* -- Signing DMG file '$DMGFILE'"
+  echo "* -- Using entitlements file '$ENTITLEMENTSFILE'"
+  if [ "$NOCODESIGNING" = 1 ]; then
+    echo "* -- NOT actually code signing, but will still make new DMG file"
+  else
+    echo "* -- Using key '$DEVELOPERID'"
+  fi
+  echo "* -- Working in temp dir '$TEMPDIR'"
+fi
+
+# Confirmation of what's about to happen
+if [ "${YES}" != 1 ]; then
+  read -r -p "* Continue? [y/N] " response
+  case $(echo "${response}" | tr '[:upper:]' '[:lower:]') in
+    yes|y)
+      echo "* Continuing."
+      ;;
+    *)
+      echo "Aborting due to negative confirmation."
+      exit
+      ;;
+  esac
+fi
+
+myexit() {
+  MSG=$1
+  CODE=$2
+  echo "$MSG"
+  exit $CODE
+}
+
+mydetachexit() {
+  MSG=$1
+  CODE=$2
+  if [ ! -z "$VOLDIR" ]; then
+    echo "* First detaching '${VOLDIR}'"
+    hdiutil detach "$VOLDIR"
+  fi
+  echo "$MSG"
+  exit $CODE
+}
+
+myparanoidrm() {
+  REMOVE="$1"
+  MSG="NOT REMOVING '${REMOVE}'"
+  # BE PARANOID BEFORE rm -Rf
+  TEST="${REMOVE}"
+  [ -z "$TEST" ] && myexit "${MSG}: Empty string." 20
+  [ "$TEST" != "${TEST/../}" ] && myexit "${MSG}: Contains .. ." 21
+  [ "$TEST" != "${TEST/\*/}" ] && myexit "${MSG}: Contains * ." 22
+  [ "$TEST" = "${TEST#$TMP}" ] && myexit "${MSG}: Doesn't start with TMP='$TMP'." 23
+  [ ${#TEST} -lt 10 ] && myexit "${MSG}: Too short." 24
+  [ ! -e "$REMOVE" ] && myexit "${MSG}: Doesn't exist." 25
+
+  # check for mounted folders
+  REALPATH=$( realpath "$REMOVE" )
+  MOUNT=$( hdiutil info | grep "Apple_HFS" | grep "$REALPATH" 2>/dev/null | head -1 | sed -e 's/^[^[:space:]]*[[:space:]]*Apple_HFS[[:space:]]*//' )
+  if [ ! -z "$MOUNT" -a -d "$MOUNT" ]; then
+    echo "* First detaching '${MOUNT}'"
+    hdiutil detach "$MOUNT"
+  fi
+
+  rm -Rf "${REMOVE}"
+}
+
+if [ "$CLEANUP" = 1 ]; then
+  # just cleaning up
+  while IFS= read -r REMOVE; do
+    echo "* Removing '${REMOVE}'"
+    myparanoidrm "${REMOVE}"
+  done <<< "$TO_REMOVE"
+  echo "* Finished cleanup. Exiting."
+  exit
+fi
+
+MOUNTROOT="${TEMPDIR}/Volume"
+mkdir -p "$MOUNTROOT"
+
+echo "* Mounting disk image '${DMGFILE}' in '${MOUNTROOT}'"
+echo "hdiutil attach -mountroot \"${MOUNTROOT}\" \"${DMGFILE}\""
+hdiutil attach -mountroot "${MOUNTROOT}" "${DMGFILE}" || myexit "Could not mount '${DMGFILE}' in '${MOUNTROOT}'. Aborting." 10
+VOLDIR=$(ls -1d "${MOUNTROOT%/}"/* | head -1)
+VOLDIR="${VOLDIR%/}" # remove trailing slash
+if [ -z "$VOLDIR" ]; then
+  myexit "Failed to find mounted volume in '${MOUNTROOT}'" 11
+fi
+VOLNAME=$(basename "$VOLDIR")
+FOUNDAPPNAME=$(ls -1d "${VOLDIR}/"*.app | head -1)
+FOUNDAPPNAME="${FOUNDAPPNAME%/}" # remove trailing slash
+FOUNDAPPNAME="${FOUNDAPPNAME%.app}" # without the ".app"
+FOUNDAPPNAME="$(basename "$FOUNDAPPNAME")"
+
+echo "* -- Found volume name '${VOLNAME}'"
+echo "* -- Found application name '${FOUNDAPPNAME}'"
+TEMPDMGDIR="${TEMPDIR%/}/${TMPDMG}"
+if [ -e "$TEMPDMGDIR" ]; then
+  mydetachexit "Folder '${TEMPDMGDIR}' already exists. Please remove it or use -s SIGNINGDMG to set a different dir name." 12
+  exit 11
+fi
+if [ "$FOUNDAPPNAME" != "$APPNAME" ]; then
+  if [ -z "$APPNAME" ]; then
+    echo "* ---- Going to set APPNAME to '${FOUNDAPPNAME}'"
+  else
+    echo "* ---- Going to reset APPNAME from '${APPNAME}' to '${FOUNDAPPNAME}'"
+  fi
+fi
+echo "* ---- Going to copy volume contents to '${TEMPDMGDIR}'"
+if [ "$NOVOLUMEICON" != 1 ]; then
+  echo "* ---- Going to try and set a volume icon to '${VOLUMEICON}'"
+fi
+
+
+# Confirmation of reset to APPNAME
+if [ "${YES}" != 1 ]; then
+  read -r -p "* Continue? [y/N] " response
+  case $(echo "${response}" | tr '[:upper:]' '[:lower:]') in
+    yes|y)
+      echo "* Continuing."
+      ;;
+    *)
+      mydetachexit "Aborting due to negative confirmation." 0
+      exit
+      ;;
+  esac
+fi
+
+APPNAME="$FOUNDAPPNAME"
+
+# Copy volume contents
+echo "* Copying '${VOLDIR}' to '${TEMPDMGDIR}'"
+ditto "$VOLDIR" "$TEMPDMGDIR"
+
+echo "* Unmounting '${VOLDIR}' and removing '${TEMPDIR}/Volume'"
+hdiutil detach "$VOLDIR"
+rmdir "${TEMPDIR}/Volume"
+
+TRUE=""
+RUNNING="RUNNING: "
+if [ "$NOCODESIGNING" = 1 ]; then
+  echo "* NO actual code signing due to -S flag"
+  TRUE="true"
+  RUNNING="NOT RUNNING: "
+fi
+
+
+echo "* Code signing in '${TEMPDMGDIR}'"
+
+
+FILE="${TEMPDMGDIR}/${APPNAME}.app/Contents/Resources/app/jre/Contents/MacOS/libjli.dylib"
+echo "* + '$FILE'"
+
+echo "${RUNNING}codesign  --remove-signature --force --deep -vvvv -s \"$DEVELOPERID\" --options runtime --entitlements \"$ENTITLEMENTSFILE\" \"$FILE\""
+$TRUE codesign  --remove-signature --force --deep -vvvv -s "$DEVELOPERID" --options runtime --entitlements "$ENTITLEMENTSFILE" "$FILE"
+
+echo "${RUNNING}codesign  --verify --deep -v \"$FILE\""
+$TRUE codesign  --verify --deep -v "$FILE"
+
+
+FILE="${TEMPDMGDIR}/${APPNAME}.app/Contents/MacOS/JavaApplicationStub"
+echo "* + '$FILE'"
+
+echo "${RUNNING}codesign  --remove-signature --force --deep -vvvv -s \"$DEVELOPERID\" --options runtime --entitlements \"$ENTITLEMENTSFILE\" \"$FILE\""
+$TRUE codesign  --remove-signature --force --deep -vvvv -s "$DEVELOPERID" --options runtime --entitlements "$ENTITLEMENTSFILE" "$FILE"
+
+
+if [ ! -z "$OUTPUTDMGFILE" ]; then
+  NEWDMGFILE="$OUTPUTDMGFILE"
+else
+  SIGNEDDIR="${DMGDIR%/}/signed"
+  NEWDMGFILE="${SIGNEDDIR}/${DMGNAME}"
+  echo "* Creating folder '${SIGNEDDIR}' for new DMG file '${DMGNAME}'"
+  mkdir -p "$SIGNEDDIR"
+fi
+
+if [ -e "$NEWDMGFILE" ]; then
+  if [ "$OVERWRITE" = 1 ]; then
+    rm "$NEWDMGFILE"
+  else
+    mydetachexit "* New DMG file already exists.  Use -O to overwrite.  Exiting." 13
+  fi
 fi
 
-if [[ -f $DMGNAME ]]; then
-    hdiutil attach $DMGNAME
-    ditto /Volumes/${FWAPP}* $TMPDMG
-    hdiutil eject /Volumes/${FWAPP}*
-    mkdir -p unsigned
-    mv -v $DMGNAME unsigned/
-    echo Moved $DMGNAME to unsigned/$DMGNAME
-    codesign  --remove-signature --force --deep -vvvv -s "Developer ID" --options runtime --entitlements $GITDIR/utils/osx_signing/entitlements.txt $TMPDMG/${FWAPP}*.app/Contents/Resources/app/jre/Contents/MacOS/libjli.dylib 
 
-    codesign  --verify --deep -v ./$TMPDMG/${FWAPP}*.app/Contents/Resources/app/jre/Contents/MacOS/libjli.dylib 
+if [ "$NOVOLUMEICON" = 1 ]; then
+  echo "* NOT setting a volume icon"
 
-    codesign --remove-signature --force --deep -vvvv -s "Developer ID" --options runtime --entitlements $GITDIR/utils/osx_signing/entitlements.txt  $TMPDMG/${FWAPP}*.app/Contents/MacOS/JavaApplicationStub
+  # without volume icon
 
-    hdiutil create -megabytes 260 -srcfolder ./$TMPDMG -volname "$BORINGVLNAME" $ARCHNAME.dmg
+  echo "* Creating new DMG file '${NEWDMGFILE}' to sign"
 
-    codesign --force --deep -vvvv -s "Developer ID" --options runtime --entitlements $GITDIR/utils/osx_signing/entitlements.txt $ARCHNAME.dmg
+  echo "hdiutil create -megabytes 260 -srcfolder \"$TEMPDMGDIR\" -volname \"$VOLNAME\" \"$NEWDMGFILE\""
+  hdiutil create -megabytes 260 -srcfolder "$TEMPDMGDIR" -volname "$VOLNAME" "$NEWDMGFILE" || mydetachexit "Could not create new DMG file '${NEWDMGFILE}'" 15
 
-    codesign --deep -vvvv $ARCHNAME.dmg
-    
-    rm -Rf $TMPDMG
 else
-    echo Can\'t find $DMGNAME - dit you set APPNAME APPVER ARCH and JVER correctly ?
+
+  # with volume icon
+
+  TEMP_RW_BASE=$(mktemp -d -p "${TEMPDIR}" -t "temp_rw")
+  TEMPDMGFILE="${TEMP_RW_BASE}.dmg"
+  TEMPMOUNTDIR="${TEMP_RW_BASE}_mount"
+
+
+  echo "* Creating temporary RW DMG file '${TMPDMGFILE}' to sign"
+
+  echo "hdiutil create -format UDRW -megabytes 260 -srcfolder \"$TEMPDMGDIR\" -volname \"$VOLNAME\" \"$TEMPDMGFILE\""
+  hdiutil create -format UDRW -megabytes 260 -srcfolder "$TEMPDMGDIR" -volname "$VOLNAME" "$TEMPDMGFILE" || mydetachexit "Could not create temporary DMG file '${TEMPDMGFILE}'" 15
+
+
+  echo "* Mounting temporary disk image '${TEMPDMGFILE}' on '${TEMPMOUNTDIR}'"
+
+  echo "hdiutil attach -mountpoint \"${TEMPMOUNTDIR}\" \"${TEMPDMGFILE}\""
+  hdiutil attach -mountpoint "${TEMPMOUNTDIR}" "${TEMPDMGFILE}" || myexit "Could not mount '${TEMPDMGFILE}' on '${TEMPMOUNTDIR}'. Aborting." 16
+
+  VOLDIR="$TEMPMOUNTDIR" # for mydetachexit
+
+
+  if [ ! -z "$VOLUMEICON" -a -e "$VOLUMEICON" -a "$USEVOLUMEICON" = 1 ]; then
+
+    echo "* Copying the volume icon '${VOLUMEICON}' to the temporary volume"
+    cp -f "$VOLUMEICON" "${TEMPMOUNTDIR}/${DEFAULTVOLUMEICONFILE}"
+
+  fi
+  if [ -e "${TEMPMOUNTDIR}/${DEFAULTVOLUMEICONFILE}" ]; then
+
+    echo "* Setting the volume icon '${DEFAULTVOLUMEICONFILE}' to the volume"
+
+    echo "SetFile -c icnC \"${TEMPMOUNTDIR}/${DEFAULTVOLUMEICONFILE}\""
+    SetFile -c icnC "${TEMPMOUNTDIR}/${DEFAULTVOLUMEICONFILE}"
+
+    echo "SetFile -a C \"${TEMPMOUNTDIR}\""
+    SetFile -a C "${TEMPMOUNTDIR}"
+
+  else
+    echo "* Could not find volume icon '${VOLUMEICON}'.  Not setting a volume icon."
+  fi
+
+
+  echo "* Unmounting '${TEMPMOUNTDIR}'"
+
+  echo "hdiutil detach \"$TEMPMOUNTDIR\""
+  hdiutil detach "$TEMPMOUNTDIR"
+
+
+  echo "* Converting temporary DMG file to new DMG file '${NEWDMGFILE}' to sign"
+
+  echo "hdiutil convert \"$TEMPDMGFILE\" -format UDZO -o \"$NEWDMGFILE\""
+  hdiutil convert "$TEMPDMGFILE" -format UDZO -o "$NEWDMGFILE" || mydetachexit "Could not convert to new DMG file '${NEWDMGFILE}'" 17
+
+
+  echo "* Removing temporary DMG file '${TEMPDMGFILE}'"
+  rm "$TEMPDMGFILE"
+
 fi
 
+
+echo "* Code signing '${NEWDMGFILE}'"
+
+echo "${RUNNING}codesign --force --deep -vvvv -s \"$DEVELOPERID\" --options runtime --entitlements \"$ENTITLEMENTSFILE\" \"$NEWDMGFILE\""
+$TRUE codesign --force --deep -vvvv -s "$DEVELOPERID" --options runtime --entitlements "$ENTITLEMENTSFILE" "$NEWDMGFILE"
+
+echo "${RUNNING}codesign --deep -vvvv \"$NEWDMGFILE\""
+$TRUE codesign --deep -vvvv "$NEWDMGFILE"
+
+
+echo "* Removing TEMPDIR '${TEMPDIR}'"
+myparanoidrm "${TEMPDIR}"
+
+echo "*** Signed DMG file at '${NEWDMGFILE}'"