Browse Source

fix(bundler): update create-dmg, fixes #1571 (#1729)

Lucas Fernandes Nogueira 4 years ago
parent
commit
f1aa12075f

+ 1 - 1
.changes/config.json

@@ -8,7 +8,7 @@
       "getPublishedVersion": "cargo search ${ pkgFile.pkg.package.name } --limit 1 | sed -nE \"s/^[^\\\"]*\\\"//; s/\\\".*//1p\"",
       "prepublish": [
         "sudo apt-get update",
-        "sudo apt-get install -y webkit2gtk-4.0",
+        "sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0",
         "cargo install cargo-audit --features=fix",
         {
           "command": "cargo generate-lockfile",

+ 5 - 0
.changes/dmg-bundle-fixes.md

@@ -0,0 +1,5 @@
+---
+"tauri-bundler": patch
+---
+
+Pull latest changes from `create-dmg`, fixing unmount issue.

+ 1 - 1
.github/workflows/artifacts-updater.yml

@@ -35,7 +35,7 @@ jobs:
         if: matrix.platform == 'ubuntu-latest'
         run: |
           sudo apt-get update
-          sudo apt-get install -y webkit2gtk-4.0
+          sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
         
       - name: Get current date
         run: echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV

+ 1 - 1
.github/workflows/build-smoke-tests.yml

@@ -69,7 +69,7 @@ jobs:
         if: matrix.platform == 'ubuntu-latest'
         run: |
           sudo apt-get update
-          sudo apt-get install -y webkit2gtk-4.0
+          sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
       - name: yarn install for cli
         working-directory: tauri/tooling/cli.js
         run: yarn

+ 2 - 2
.github/workflows/core-lint-fmt.yml

@@ -24,7 +24,7 @@ jobs:
       - name: install webkit2gtk
         run: |
           sudo apt-get update
-          sudo apt-get install -y webkit2gtk-4.0
+          sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
 
       - uses: actions-rs/toolchain@v1
         with:
@@ -151,7 +151,7 @@ jobs:
       - name: install webkit2gtk
         run: |
           sudo apt-get update
-          sudo apt-get install -y webkit2gtk-4.0
+          sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
 
       - uses: actions-rs/toolchain@v1
         with:

+ 1 - 1
.github/workflows/covector-version-or-publish.yml

@@ -70,7 +70,7 @@ jobs:
       - name: install webkit2gtk
         run: |
           sudo apt-get update
-          sudo apt-get install -y webkit2gtk-4.0
+          sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
       - name: generate rust docs
         working-directory: ./tauri/core/tauri
         run: cargo doc --no-deps

+ 1 - 1
.github/workflows/smoke-test-prod.yml

@@ -37,7 +37,7 @@ jobs:
         if: matrix.platform == 'ubuntu-latest'
         run: |
           sudo apt-get update
-          sudo apt-get install -y webkit2gtk-4.0
+          sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
       - name: cache rust bin
         id: cache_rust_bin
         uses: actions/cache@v1

+ 2 - 2
.github/workflows/test-bundler.yml

@@ -35,7 +35,7 @@ jobs:
         if: matrix.platform == 'ubuntu-latest'
         run: |
           sudo apt-get update
-          sudo apt-get install -y webkit2gtk-4.0
+          sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
 
       - name: Get current date
         run: echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
@@ -100,7 +100,7 @@ jobs:
         if: matrix.platform == 'ubuntu-latest'
         run: |
           sudo apt-get update
-          sudo apt-get install -y webkit2gtk-4.0
+          sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
       - name: clippy check
         uses: actions-rs/clippy-check@v1
         with:

+ 2 - 2
.github/workflows/test-core.yml

@@ -37,7 +37,7 @@ jobs:
         if: matrix.platform == 'ubuntu-latest'
         run: |
           sudo apt-get update
-          sudo apt-get install -y webkit2gtk-4.0
+          sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
 
       - name: Get current date
         run: echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
@@ -161,7 +161,7 @@ jobs:
         if: matrix.platform == 'ubuntu-latest'
         run: |
           sudo apt-get update
-          sudo apt-get install -y webkit2gtk-4.0
+          sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
 
       - name: Get current date
         run: echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV

+ 2 - 2
.github/workflows/test-cta.yml

@@ -47,7 +47,7 @@ jobs:
       - name: install webkit2gtk
         run: |
           sudo apt-get update
-          sudo apt-get install -y webkit2gtk-4.0
+          sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
       - run: yarn
         working-directory: tooling/create-tauri-app
       - run: yarn build
@@ -83,7 +83,7 @@ jobs:
       - name: install webkit2gtk
         run: |
           sudo apt-get update
-          sudo apt-get install -y webkit2gtk-4.0
+          sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
       - run: yarn
         working-directory: tooling/create-tauri-app
       - run: yarn build

+ 1 - 1
.github/workflows/udeps.yml

@@ -90,7 +90,7 @@ jobs:
     - name: Install required packages
       run: |
         sudo apt-get update
-        sudo apt-get install -y webkit2gtk-4.0
+        sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
 
     - uses: actions-rs/cargo@v1
       with:

+ 1 - 1
.github/workflows/update-docs.yml

@@ -32,7 +32,7 @@ jobs:
       - name: install webkit2gtk
         run: |
           sudo apt-get update
-          sudo apt-get install -y webkit2gtk-4.0
+          sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0
       - name: generate rust docs
         working-directory: ./tauri/core/tauri
         run: cargo doc --no-deps

+ 4 - 13
tooling/bundler/src/bundle/common.rs

@@ -6,7 +6,7 @@ use crate::Settings;
 use std::{
   ffi::OsStr,
   fs::{self, File},
-  io::{self, BufRead, BufReader, BufWriter, Write},
+  io::{self, BufWriter, Write},
   path::{Component, Path, PathBuf},
   process::{Command, Stdio},
 };
@@ -214,25 +214,16 @@ pub fn print_info(message: &str) -> crate::Result<()> {
 
 pub fn execute_with_verbosity(cmd: &mut Command, settings: &Settings) -> crate::Result<()> {
   let stdio_config = if settings.is_verbose() {
-    Stdio::piped
+    Stdio::inherit
   } else {
     Stdio::null
   };
-  let mut child = cmd
+  let status = cmd
     .stdout(stdio_config())
     .stderr(stdio_config())
-    .spawn()
+    .status()
     .expect("failed to spawn command");
-  if settings.is_verbose() {
-    let stdout = child.stdout.as_mut().expect("Failed to get stdout handle");
-    let reader = BufReader::new(stdout);
 
-    for line in reader.lines() {
-      println!("{}", line.expect("Failed to get line"));
-    }
-  }
-
-  let status = child.wait()?;
   if status.success() {
     Ok(())
   } else {

+ 10 - 6
tooling/bundler/src/bundle/macos/dmg.rs

@@ -41,7 +41,7 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result<
   let dmg_name = format!("{}.dmg", &package_base_name);
   let dmg_path = output_path.join(&dmg_name);
 
-  let product_name = &format!("{}.app", &package_base_name);
+  let product_name = &format!("{}.app", settings.main_binary_name());
   let bundle_dir = settings.project_out_directory().join("bundle/macos");
 
   let support_directory_path = output_path.join("support");
@@ -58,7 +58,6 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result<
 
   // create paths for script
   let bundle_script_path = output_path.join("bundle_dmg.sh");
-  let license_script_path = support_directory_path.join("dmg-license.py");
 
   common::print_bundling(format!("{:?}", &dmg_path).as_str())?;
 
@@ -72,15 +71,14 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result<
     include_str!("templates/dmg/template.applescript"),
   )?;
   write(
-    &license_script_path,
-    include_str!("templates/dmg/dmg-license.py"),
+    support_directory_path.join("eula-resources-template.xml"),
+    include_str!("templates/dmg/eula-resources-template.xml"),
   )?;
 
   // chmod script for execution
   Command::new("chmod")
     .arg("777")
     .arg(&bundle_script_path)
-    .arg(&license_script_path)
     .current_dir(output_path)
     .stdout(Stdio::piped())
     .stderr(Stdio::piped())
@@ -109,9 +107,15 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result<
     &product_name,
   ];
 
+  #[allow(unused_assignments)]
+  let mut license_path_ref = "".to_string();
   if let Some(license_path) = &settings.macos().license {
     args.push("--eula");
-    args.push(license_path);
+    license_path_ref = env::current_dir()?
+      .join(license_path)
+      .to_string_lossy()
+      .to_string();
+    args.push(&license_path_ref);
   }
 
   // Issue #592 - Building MacOS dmg files on CI

+ 138 - 72
tooling/bundler/src/bundle/macos/templates/dmg/bundle_dmg

@@ -6,7 +6,8 @@
 # Create a read-only disk image of the contents of a folder
 # forked from https://github.com/andreyvit/create-dmg
 
-set -eux;
+# Bail out on any unhandled errors
+set -ex;
 
 function pure_version() {
 	echo '1.0.0.6'
@@ -19,8 +20,8 @@ function version() {
 function usage() {
 	version
 	echo "Creates a fancy DMG file."
-	echo "Usage:  $(basename $0) [options] <output_name.dmg> <source_folder>"
-	echo "All contents of source_folder will be copied into the disk image."
+	echo "Usage:  $(basename "$0") [options] <output_name.dmg> <source_folder>"
+	echo "All contents of <source_folder> will be copied into the disk image."
 	echo "Options:"
 	echo "  --volname name"
 	echo "      set volume name (displayed in the Finder sidebar and window title)"
@@ -40,8 +41,6 @@ function usage() {
 	echo "      set position of the file's icon"
 	echo "  --hide-extension file_name"
 	echo "      hide the extension of file"
-	echo "  --custom-icon file_name custom_icon_or_sample_file x y"
-	echo "      set position and custom icon"
 	echo "  --app-drop-link x y"
 	echo "      make a drop link to Applications, at location x,y"
 	echo "  --ql-drop-link x y"
@@ -61,9 +60,7 @@ function usage() {
 	echo "  --hdiutil-quiet"
 	echo "      execute hdiutil in quiet mode"
 	echo "  --sandbox-safe"
-	echo "      execute hdiutil with sandbox compatibility and do not bless"
-	echo "  --rez rez_path"
-	echo "      use custom path to Rez tool"
+	echo "      execute hdiutil with sandbox compatibility, do not bless and do not execute the cosmetic AppleScript"
 	echo "  --version         show tool version number"
 	echo "  -h, --help        display this help"
 	exit 0
@@ -82,10 +79,11 @@ IMAGEKEY=""
 HDIUTIL_VERBOSITY=""
 SANDBOX_SAFE=0
 SKIP_JENKINS=0
+MAXIMUM_UNMOUNTING_ATTEMPTS=3
 POSITION_CLAUSE=""
 HIDING_CLAUSE=""
 
-while [ ! -z ${1+x} ] && test "${1:0:1}" = "-"; do
+while [[ "${1:0:1}" = "-" ]]; do
 	case $1 in
 	--volname)
 		VOLUME_NAME="$2"
@@ -95,7 +93,7 @@ while [ ! -z ${1+x} ] && test "${1:0:1}" = "-"; do
 		shift; shift;;
 	--background)
 		BACKGROUND_FILE="$2"
-		BACKGROUND_FILE_NAME="$(basename $BACKGROUND_FILE)"
+		BACKGROUND_FILE_NAME="$(basename "$BACKGROUND_FILE")"
 		BACKGROUND_CLAUSE="set background picture of opts to file \".background:$BACKGROUND_FILE_NAME\""
 		REPOSITION_HIDDEN_FILES_CLAUSE="set position of every item to {theBottomRightX + 100, 100}"
 		shift; shift;;
@@ -119,8 +117,6 @@ while [ ! -z ${1+x} ] && test "${1:0:1}" = "-"; do
 		HIDING_CLAUSE="${HIDING_CLAUSE}set the extension hidden of item \"$2\" to true
 		"
 		shift; shift;;
-	--custom-icon)
-		shift; shift; shift; shift; shift;;
 	-h | --help)
 		usage;;
 	--version)
@@ -165,14 +161,11 @@ while [ ! -z ${1+x} ] && test "${1:0:1}" = "-"; do
 	--sandbox-safe)
 		SANDBOX_SAFE=1
 		shift;;
-	--rez)
-		REZ_PATH=$2
-		shift; shift;;
 	--skip-jenkins)
 		SKIP_JENKINS=1
 		shift;;
 	-*)
-		echo "Unknown option $1. Run with --help for help."
+		echo "Unknown option: $1. Run with --help for help."
 		exit 1;;
 	esac
 	case $FORMAT in
@@ -183,10 +176,10 @@ while [ ! -z ${1+x} ] && test "${1:0:1}" = "-"; do
 	esac
 done
 
-[ -z ${2+x} ] && {
+if [[ -z "$2" ]]; then
 	echo "Not enough arguments. Invoke with --help for help."
 	exit 1
-}
+fi
 
 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
 DMG_PATH="$1"
@@ -196,7 +189,16 @@ DMG_NAME="$(basename "$DMG_PATH")"
 DMG_TEMP_NAME="$DMG_DIR/rw.${DMG_NAME}"
 SRC_FOLDER="$(cd "$2" > /dev/null; pwd)"
 
-[ -z ${VOLUME_NAME+x} ] && VOLUME_NAME="$(basename "$DMG_PATH" .dmg)"
+# Argument validation checks
+
+if [[ "${DMG_PATH: -4}" != ".dmg" ]]; then
+	echo "Output file name must end with a .dmg extension. Run 'create-dmg --help' for help."
+	exit 1
+fi
+
+if [[ -z "$VOLUME_NAME" ]]; then
+	VOLUME_NAME="$(basename "$DMG_PATH" .dmg)"
+fi
 
 # brew formula will set this as 1 and embed the support scripts
 BREW_INSTALL=0
@@ -210,14 +212,16 @@ if [ $BREW_INSTALL -eq 0 ]; then
 	}
 fi
 
-if [ -f "$SRC_FOLDER/.DS_Store" ]; then
+if [[ -f "$SRC_FOLDER/.DS_Store" ]]; then
 	echo "Deleting any .DS_Store in source folder"
 	rm "$SRC_FOLDER/.DS_Store"
 fi
 
 # Create the image
 echo "Creating disk image..."
-test -f "${DMG_TEMP_NAME}" && rm -f "${DMG_TEMP_NAME}"
+if [[ -f "${DMG_TEMP_NAME}" ]]; then
+	rm -f "${DMG_TEMP_NAME}"
+fi
 
 # Using Megabytes since hdiutil fails with very large Byte numbers
 function blocks_to_megabytes() {
@@ -228,13 +232,13 @@ function blocks_to_megabytes() {
 
 function get_size() {
 	# Get block size in disk
-	bytes_size=`du -s "$1" | sed -e 's/	.*//g'`
-	echo `blocks_to_megabytes $bytes_size`
+	bytes_size=$(du -s "$1" | sed -e 's/	.*//g')
+	echo $(blocks_to_megabytes "$bytes_size")
 }
 
 # Create the DMG with the specified size or the hdiutil estimation
 CUSTOM_SIZE=''
-if [ ! -z ${DISK_IMAGE_SIZE+x} ]; then
+if [[ -n "$DISK_IMAGE_SIZE" ]]; then
 	CUSTOM_SIZE="-size ${DISK_IMAGE_SIZE}m"
 fi
 
@@ -247,18 +251,17 @@ else
 fi
 
 # Get the created DMG actual size
-DISK_IMAGE_SIZE=`get_size "${DMG_TEMP_NAME}"`
+DISK_IMAGE_SIZE=$(get_size "${DMG_TEMP_NAME}")
 
 # Use the custom size if bigger
-if [ $SANDBOX_SAFE -eq 1 ] && [ !  -z ${DISK_IMAGE_SIZE_CUSTOM+x} ] && [ $DISK_IMAGE_SIZE_CUSTOM -gt $DISK_IMAGE_SIZE ]; then
+if [[ $SANDBOX_SAFE -eq 1 ]] && [[ -n "$DISK_IMAGE_SIZE_CUSTOM" ]] && [[ $DISK_IMAGE_SIZE_CUSTOM -gt $DISK_IMAGE_SIZE ]]; then
 	DISK_IMAGE_SIZE=$DISK_IMAGE_SIZE_CUSTOM
 fi
 
-# Estimate the additional soruces size
-if [ ! -z ${ADD_FILE_SOURCES+x} ]; then
-	for i in "${!ADD_FILE_SOURCES[@]}"
-	do
-		SOURCE_SIZE=`get_size "${ADD_FILE_SOURCES[$i]}"`
+# Estimate the additional sources size
+if [[ -n "$ADD_FILE_SOURCES" ]]; then
+	for i in "${!ADD_FILE_SOURCES[@]}"; do
+		SOURCE_SIZE=$(get_size "${ADD_FILE_SOURCES[$i]}")
 		DISK_IMAGE_SIZE=$(expr $DISK_IMAGE_SIZE + $SOURCE_SIZE)
 	done
 fi
@@ -266,57 +269,64 @@ fi
 # Add extra space for additional resources
 DISK_IMAGE_SIZE=$(expr $DISK_IMAGE_SIZE + 20)
 
+# Make sure target image size is within limits
+MIN_DISK_IMAGE_SIZE=$(hdiutil resize -limits "${DMG_TEMP_NAME}" | awk 'NR=1{print int($1/2048+1)}')
+if [ $MIN_DISK_IMAGE_SIZE -gt $DISK_IMAGE_SIZE ]; then
+  DISK_IMAGE_SIZE=$MIN_DISK_IMAGE_SIZE
+fi
+
 # Resize the image for the extra stuff
 hdiutil resize ${HDIUTIL_VERBOSITY} -size ${DISK_IMAGE_SIZE}m "${DMG_TEMP_NAME}"
 
-# mount it
+# mount the new DMG
 echo "Mounting disk image..."
 MOUNT_DIR="/Volumes/${VOLUME_NAME}"
 
-# try unmount dmg if it was mounted previously (e.g. developer mounted dmg, installed app and forgot to unmount it)
-DEV_NAME=$(hdiutil info | egrep --color=never '^/dev/' | sed 1q | awk '{print $1}')
-if [ test -d "${MOUNT_DIR}" ]; then
+# Unmount leftover dmg if it was mounted previously (e.g. developer mounted dmg, installed app and forgot to unmount it)
+if [[ -d "${MOUNT_DIR}" ]]; then
   echo "Unmounting previously mounted disk image..."
+	DEV_NAME=$(hdiutil info | egrep --color=never '^/dev/' | sed 1q | awk '{print $1}')
   hdiutil detach "${DEV_NAME}"
 fi
 
+echo "Mounting disk image..."
+
 echo "Mount directory: $MOUNT_DIR"
 DEV_NAME=$(hdiutil attach -readwrite -noverify -noautoopen "${DMG_TEMP_NAME}" | egrep --color=never '^/dev/' | sed 1q | awk '{print $1}')
 echo "Device name:     $DEV_NAME"
 
-if [ ! -z ${BACKGROUND_FILE+x} ]; then
-	echo "Copying background file..."
-	test -d "$MOUNT_DIR/.background" || mkdir "$MOUNT_DIR/.background"
+if [[ -n "$BACKGROUND_FILE" ]]; then
+	echo "Copying background file '$BACKGROUND_FILE'..."
+	[[ -d "$MOUNT_DIR/.background" ]] || mkdir "$MOUNT_DIR/.background"
 	cp "$BACKGROUND_FILE" "$MOUNT_DIR/.background/$BACKGROUND_FILE_NAME"
 fi
 
-if [ ! -z ${APPLICATION_LINK+x} ]; then
+if [[ -n "$APPLICATION_LINK" ]]; then
 	echo "making link to Applications dir"
 	test -d "$MOUNT_DIR/Applications" || ln -s /Applications "$MOUNT_DIR/Applications"
 fi
 
-if [ ! -z ${QL_LINK+x} ]; then
+if [[ -n "$QL_LINK" ]]; then
 	echo "making link to QuickLook install dir"
 	ln -s "/Library/QuickLook" "$MOUNT_DIR/QuickLook"
 fi
 
-if [ ! -z ${VOLUME_ICON_FILE+x} ]; then
+if [[ -n "$VOLUME_ICON_FILE" ]]; then
 	echo "Copying volume icon file '$VOLUME_ICON_FILE'..."
 	cp "$VOLUME_ICON_FILE" "$MOUNT_DIR/.VolumeIcon.icns"
 	SetFile -c icnC "$MOUNT_DIR/.VolumeIcon.icns"
 fi
 
-if [ ! -z ${ADD_FILE_SOURCES+x} ]; then
+if [[ -n "$ADD_FILE_SOURCES" ]]; then
 	echo "Copying custom files..."
-	for i in "${!ADD_FILE_SOURCES[@]}"
-	do
+	for i in "${!ADD_FILE_SOURCES[@]}"; do
 		echo "${ADD_FILE_SOURCES[$i]}"
 		cp -a "${ADD_FILE_SOURCES[$i]}" "$MOUNT_DIR/${ADD_FILE_TARGETS[$i]}"
 	done
 fi
 
-# run applescript
-APPLESCRIPT=$(mktemp -t createdmg.tmp.XXXXXXXXXX)
+# run AppleScript to do all the Finder cosmetic stuff
+APPLESCRIPT_FILE=$(mktemp -t createdmg.tmp.XXXXXXXXXX)
 
 function applescript_source() {
 	if [ $BREW_INSTALL -eq 0 ]; then
@@ -328,14 +338,34 @@ EOS
 	fi
 }
 
-if [ $SKIP_JENKINS -eq 0 ]; then
-	applescript_source | sed -e "s/WINX/$WINX/g" -e "s/WINY/$WINY/g" -e "s/WINW/$WINW/g" -e "s/WINH/$WINH/g" -e "s/BACKGROUND_CLAUSE/$BACKGROUND_CLAUSE/g" -e "s/REPOSITION_HIDDEN_FILES_CLAUSE/$REPOSITION_HIDDEN_FILES_CLAUSE/g" -e "s/ICON_SIZE/$ICON_SIZE/g" -e "s/TEXT_SIZE/$TEXT_SIZE/g" | perl -pe  "s/POSITION_CLAUSE/$POSITION_CLAUSE/g" | perl -pe "s/QL_CLAUSE/$QL_CLAUSE/g" | perl -pe "s/APPLICATION_CLAUSE/$APPLICATION_CLAUSE/g" | perl -pe "s/HIDING_CLAUSE/$HIDING_CLAUSE/" >"$APPLESCRIPT"
-	sleep 2 # pause to workaround occasional "Can’t get disk" (-1728) issues
-	echo "Running Applescript: /usr/bin/osascript \"${APPLESCRIPT}\" \"${VOLUME_NAME}\""
-	(/usr/bin/osascript "${APPLESCRIPT}" "${VOLUME_NAME}" || if [[ "$?" -ne 0 ]]; then echo "Failed running AppleScript"; hdiutil detach "${DEV_NAME}"; exit 64; fi)
-	echo "Done running the applescript..."
-	sleep 4
-	rm "$APPLESCRIPT"
+if [[ $SANDBOX_SAFE -eq 1 ]]; then
+	echo "Skipping Finder-prettifying AppleScript because we are in Sandbox..."
+else
+	if [[ $SKIP_JENKINS -eq 0 ]]; then
+		applescript_source \
+			| sed -e "s/WINX/$WINX/g" -e "s/WINY/$WINY/g" -e "s/WINW/$WINW/g" \
+					-e "s/WINH/$WINH/g" -e "s/BACKGROUND_CLAUSE/$BACKGROUND_CLAUSE/g" \
+					-e "s/REPOSITION_HIDDEN_FILES_CLAUSE/$REPOSITION_HIDDEN_FILES_CLAUSE/g" \
+					-e "s/ICON_SIZE/$ICON_SIZE/g" -e "s/TEXT_SIZE/$TEXT_SIZE/g" \
+			| perl -pe "s/POSITION_CLAUSE/$POSITION_CLAUSE/g" \
+			| perl -pe "s/QL_CLAUSE/$QL_CLAUSE/g" \
+			| perl -pe "s/APPLICATION_CLAUSE/$APPLICATION_CLAUSE/g" \
+			| perl -pe "s/HIDING_CLAUSE/$HIDING_CLAUSE/" \
+			> "$APPLESCRIPT_FILE"
+		sleep 2 # pause to workaround occasional "Can’t get disk" (-1728) issues  
+		echo "Running AppleScript to make Finder stuff pretty: /usr/bin/osascript \"${APPLESCRIPT_FILE}\" \"${VOLUME_NAME}\""
+		if /usr/bin/osascript "${APPLESCRIPT_FILE}" "${VOLUME_NAME}"; then
+			# Okay, we're cool
+			true
+		else
+			echo >&2 "Failed running AppleScript"
+			hdiutil detach "${DEV_NAME}"
+			exit 64
+		fi
+		echo "Done running the AppleScript..."
+		sleep 4
+		rm "$APPLESCRIPT_FILE"
+	fi
 fi
 
 # make sure it's not world writeable
@@ -344,7 +374,7 @@ chmod -Rf go-w "${MOUNT_DIR}" &> /dev/null || true
 echo "Done fixing permissions."
 
 # make the top window open itself on mount:
-if [ $SANDBOX_SAFE -eq 0 ]; then
+if [[ $SANDBOX_SAFE -eq 0 ]]; then
 	echo "Blessing started"
 	bless --folder "${MOUNT_DIR}" --openfolder "${MOUNT_DIR}"
 	echo "Blessing finished"
@@ -352,38 +382,74 @@ else
 	echo "Skipping blessing on sandbox"
 fi
 
-if [ ! -z ${VOLUME_ICON_FILE+x} ]; then
+if [[ -n "$VOLUME_ICON_FILE" ]]; then
 	# tell the volume that it has a special file attribute
 	SetFile -a C "$MOUNT_DIR"
 fi
 
+# Delete unnecessary file system events log
+echo "Deleting .fseventsd"
+rm -rf "${MOUNT_DIR}/.fseventsd"
+
 # unmount
-echo "Unmounting disk image..."
-hdiutil detach "${DEV_NAME}"
+unmounting_attempts=0
+until
+  echo "Unmounting disk image..."
+  (( unmounting_attempts++ ))
+  hdiutil detach "${DEV_NAME}"
+	exit_code=$?
+	(( exit_code ==  0 )) && break            # nothing goes wrong
+	(( exit_code != 16 )) && exit $exit_code  # exit with the original exit code
+	# The above statement returns 1 if test failed (exit_code == 16).
+	#   It can make the code in the {do... done} block to be executed
+do
+  (( unmounting_attempts == MAXIMUM_UNMOUNTING_ATTEMPTS )) && exit 16  # patience exhausted, exit with code EBUSY
+	echo "Wait a moment..."
+  sleep $(( 1 * (2 ** unmounting_attempts) ))
+done
+unset unmounting_attempts
 
 # compress image
 echo "Compressing disk image..."
-hdiutil convert ${HDIUTIL_VERBOSITY} "${DMG_TEMP_NAME}" -format ${FORMAT} ${IMAGEKEY} -o "${DMG_DIR}/${DMG_NAME}"
+hdiutil convert ${HDIUTIL_VERBOSITY} "${DMG_TEMP_NAME}" -format "${FORMAT}" ${IMAGEKEY} -o "${DMG_DIR}/${DMG_NAME}"
 rm -f "${DMG_TEMP_NAME}"
 
 # adding EULA resources
-if [ ! -z ${EULA_RSRC+x} ]; then
+if [[ -n "${EULA_RSRC}" && "${EULA_RSRC}" != "-null-" ]]; then
 	echo "adding EULA resources"
-
-	REZ_ARG=""
-	if [ ! -z ${REZ_PATH+x} ]; then
-		REZ_ARG="--rez ${REZ_PATH}"
-	fi
-	if [ $BREW_INSTALL -eq 0 ]; then
-		"${AUX_PATH}/dmg-license.py" "${DMG_DIR}/${DMG_NAME}" "${EULA_RSRC}" ${REZ_ARG}
+	#
+	# Use udifrez instead flatten/rez/unflatten
+	# https://github.com/create-dmg/create-dmg/issues/109
+	#
+	# Based on a thread from dawn2dusk & peterguy
+	# https://developer.apple.com/forums/thread/668084
+	#
+	EULA_RESOURCES_FILE=$(mktemp -t createdmg.tmp.XXXXXXXXXX)
+	EULA_FORMAT=$(file -b "${EULA_RSRC}")
+	if [[ ${EULA_FORMAT} == 'Rich Text Format data'* ]] ; then
+		EULA_FORMAT='RTF '
 	else
-		python - "${DMG_DIR}/${DMG_NAME}" "${EULA_RSRC}" ${REZ_ARG} <<-'EOS'
-		# BREW_INLINE_LICENSE_PLACEHOLDER
-EOS
+		EULA_FORMAT='TEXT'
 	fi
+
+	# Encode the EULA to base64
+	# Replace 'openssl base64' with 'base64' if Mac OS X 10.6 support is no more needed
+	# EULA_DATA="$(base64 -b 52 "${EULA_RSRC}" | sed s$'/^\(.*\)$/\t\t\t\\1/')"
+	EULA_DATA="$(openssl base64 -in "${EULA_RSRC}" | tr -d '\n' | awk '{gsub(/.{52}/,"&\n")}1' | sed s$'/^\(.*\)$/\t\t\t\\1/')"
+	# Fill the template with the custom EULA contents
+	eval "cat > \"${EULA_RESOURCES_FILE}\" <<EOF                                                                                                                  
+	$(<${AUX_PATH}/eula-resources-template.xml)
+	EOF
+	"
+	# Apply the resources
+	hdiutil udifrez -xml "${EULA_RESOURCES_FILE}" '' -quiet "${DMG_DIR}/${DMG_NAME}" || {
+		echo "Failed to add the EULA license"
+		exit 1
+	}
+	echo "Successfully added the EULA license"
 fi
 
-if [ ! -z ${NOINTERNET+x} && -a "${NOINTERNET}" == 1 ]; then
+if [[ -n "${NOINTERNET}" && "${NOINTERNET}" == 1 ]]; then
 	echo "not setting 'internet-enable' on the dmg"
 else
 	# check if hdiutil supports internet-enable
@@ -398,4 +464,4 @@ else
 fi
 
 echo "Disk image done"
-exit 0
+exit 0

+ 0 - 168
tooling/bundler/src/bundle/macos/templates/dmg/dmg-license.py

@@ -1,168 +0,0 @@
-#!/usr/bin/env python
-"""
-// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-This script adds a license file to a DMG. Requires Xcode and a plain ascii text
-license file.
-Obviously only runs on a Mac.
-
-Copyright (C) 2011-2013 Jared Hobbs
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-"""
-from __future__ import print_function
-import os
-import sys
-import tempfile
-import optparse
-
-REZ_PATH = os.popen('xcode-select --print-path', 'r').read().strip()
-
-class Path(str):
-    def __enter__(self):
-        return self
-
-    def __exit__(self, type, value, traceback):
-        os.unlink(self)
-
-
-def mktemp(dir=None, suffix=''):
-    (fd, filename) = tempfile.mkstemp(dir=dir, suffix=suffix)
-    os.close(fd)
-    return Path(filename)
-
-
-def main(options, args):
-    dmgFile, license = args
-    with mktemp('.') as tmpFile:
-        with open(tmpFile, 'w') as f:
-            f.write("""data 'TMPL' (128, "LPic") {
-        $"1344 6566 6175 6C74 204C 616E 6775 6167"
-        $"6520 4944 4457 5244 0543 6F75 6E74 4F43"
-        $"4E54 042A 2A2A 2A4C 5354 430B 7379 7320"
-        $"6C61 6E67 2049 4444 5752 441E 6C6F 6361"
-        $"6C20 7265 7320 4944 2028 6F66 6673 6574"
-        $"2066 726F 6D20 3530 3030 4457 5244 1032"
-        $"2D62 7974 6520 6C61 6E67 7561 6765 3F44"
-        $"5752 4404 2A2A 2A2A 4C53 5445"
-};
-
-data 'LPic' (5000) {
-        $"0000 0002 0000 0000 0000 0000 0004 0000"
-};
-
-data 'STR#' (5000, "English buttons") {
-        $"0006 0D45 6E67 6C69 7368 2074 6573 7431"
-        $"0541 6772 6565 0844 6973 6167 7265 6505"
-        $"5072 696E 7407 5361 7665 2E2E 2E7A 4966"
-        $"2079 6F75 2061 6772 6565 2077 6974 6820"
-        $"7468 6520 7465 726D 7320 6F66 2074 6869"
-        $"7320 6C69 6365 6E73 652C 2063 6C69 636B"
-        $"2022 4167 7265 6522 2074 6F20 6163 6365"
-        $"7373 2074 6865 2073 6F66 7477 6172 652E"
-        $"2020 4966 2079 6F75 2064 6F20 6E6F 7420"
-        $"6167 7265 652C 2070 7265 7373 2022 4469"
-        $"7361 6772 6565 2E22"
-};
-
-data 'STR#' (5002, "English") {
-        $"0006 0745 6E67 6C69 7368 0541 6772 6565"
-        $"0844 6973 6167 7265 6505 5072 696E 7407"
-        $"5361 7665 2E2E 2E7B 4966 2079 6F75 2061"
-        $"6772 6565 2077 6974 6820 7468 6520 7465"
-        $"726D 7320 6F66 2074 6869 7320 6C69 6365"
-        $"6E73 652C 2070 7265 7373 2022 4167 7265"
-        $"6522 2074 6F20 696E 7374 616C 6C20 7468"
-        $"6520 736F 6674 7761 7265 2E20 2049 6620"
-        $"796F 7520 646F 206E 6F74 2061 6772 6565"
-        $"2C20 7072 6573 7320 2244 6973 6167 7265"
-        $"6522 2E"
-};\n\n""")
-            with open(license, 'r') as l:
-                kind = 'RTF ' if license.lower().endswith('.rtf') else 'TEXT'
-                f.write('data \'%s\' (5000, "English") {\n' % kind)
-                def escape(s):
-                    return s.strip().replace('\\', '\\\\').replace('"', '\\"').replace('\0', '')
-
-                for line in l:
-                    line = escape(line)
-                    for liner in [line[i:i+1000] for i in range(0, len(line), 1000)]:
-                        f.write('    "' + liner + '"\n')
-                    f.write('    "' + '\\n"\n')
-                f.write('};\n\n')
-            f.write("""data 'styl' (5000, "English") {
-        $"0003 0000 0000 000C 0009 0014 0000 0000"
-        $"0000 0000 0000 0000 0027 000C 0009 0014"
-        $"0100 0000 0000 0000 0000 0000 002A 000C"
-        $"0009 0014 0000 0000 0000 0000 0000"
-};\n""")
-        os.system('hdiutil unflatten -quiet "%s"' % dmgFile)
-        ret = os.system('%s -a %s -o "%s"' %
-                        (options.rez, tmpFile, dmgFile))
-        os.system('hdiutil flatten -quiet "%s"' % dmgFile)
-        if options.compression is not None:
-            os.system('cp %s %s.temp.dmg' % (dmgFile, dmgFile))
-            os.remove(dmgFile)
-            if options.compression == "bz2":
-                os.system('hdiutil convert %s.temp.dmg -format UDBZ -o %s' %
-                          (dmgFile, dmgFile))
-            elif options.compression == "gz":
-                os.system('hdiutil convert %s.temp.dmg -format ' % dmgFile +
-                          'UDZO -imagekey zlib-devel=9 -o %s' % dmgFile)
-            os.remove('%s.temp.dmg' % dmgFile)
-    if ret == 0:
-        print("Successfully added license to '%s'" % dmgFile)
-    else:
-        print("Failed to add license to '%s'" % dmgFile)
-
-if __name__ == '__main__':
-    parser = optparse.OptionParser()
-    parser.set_usage("""%prog <dmgFile> <licenseFile> [OPTIONS]
-  This program adds a software license agreement to a DMG file.
-  It requires Xcode and either a plain ascii text <licenseFile>
-  or a <licenseFile.rtf> with the RTF contents.
-
-  See --help for more details.""")
-    parser.add_option(
-        '--rez',
-        '-r',
-        action='store',
-        default=REZ_PATH,
-        help='The path to the Rez tool. Defaults to %default'
-    )
-    parser.add_option(
-        '--compression',
-        '-c',
-        action='store',
-        choices=['bz2', 'gz'],
-        default=None,
-        help='Optionally compress dmg using specified compression type. '
-             'Choices are bz2 and gz.'
-    )
-    options, args = parser.parse_args()
-    cond = len(args) != 2
-    if not os.path.exists(options.rez):
-        print('Failed to find Rez at "%s"! Run `xcode-select --install` and try again.\n' % options.rez)
-        cond = True
-    if cond:
-        parser.print_usage()
-        sys.exit(1)
-    main(options, args)

+ 105 - 0
tooling/bundler/src/bundle/macos/templates/dmg/eula-resources-template.xml

@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>LPic</key>
+	<array>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>
+			AAAAAgAAAAAAAAAAAAQAAA==
+			</data>
+			<key>ID</key>
+			<string>5000</string>
+			<key>Name</key>
+			<string></string>
+		</dict>
+	</array>
+	<key>STR#</key>
+	<array>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>
+			AAYNRW5nbGlzaCB0ZXN0MQVBZ3JlZQhEaXNhZ3JlZQVQcmludAdT
+			YXZlLi4ueklmIHlvdSBhZ3JlZSB3aXRoIHRoZSB0ZXJtcyBvZiB0
+			aGlzIGxpY2Vuc2UsIGNsaWNrICJBZ3JlZSIgdG8gYWNjZXNzIHRo
+			ZSBzb2Z0d2FyZS4gIElmIHlvdSBkbyBub3QgYWdyZWUsIHByZXNz
+			ICJEaXNhZ3JlZS4i
+			</data>
+			<key>ID</key>
+			<string>5000</string>
+			<key>Name</key>
+			<string>English buttons</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>
+			AAYHRW5nbGlzaAVBZ3JlZQhEaXNhZ3JlZQVQcmludAdTYXZlLi4u
+			e0lmIHlvdSBhZ3JlZSB3aXRoIHRoZSB0ZXJtcyBvZiB0aGlzIGxp
+			Y2Vuc2UsIHByZXNzICJBZ3JlZSIgdG8gaW5zdGFsbCB0aGUgc29m
+			dHdhcmUuICBJZiB5b3UgZG8gbm90IGFncmVlLCBwcmVzcyAiRGlz
+			YWdyZWUiLg==
+			</data>
+			<key>ID</key>
+			<string>5002</string>
+			<key>Name</key>
+			<string>English</string>
+		</dict>
+	</array>
+	<key>${EULA_FORMAT}</key>
+	<array>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>
+${EULA_DATA}
+			</data>
+			<key>ID</key>
+			<string>5000</string>
+			<key>Name</key>
+			<string>English</string>
+		</dict>
+	</array>
+	<key>TMPL</key>
+	<array>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>
+			E0RlZmF1bHQgTGFuZ3VhZ2UgSUREV1JEBUNvdW50T0NOVAQqKioq
+			TFNUQwtzeXMgbGFuZyBJRERXUkQebG9jYWwgcmVzIElEIChvZmZz
+			ZXQgZnJvbSA1MDAwRFdSRBAyLWJ5dGUgbGFuZ3VhZ2U/RFdSRAQq
+			KioqTFNURQ==
+			</data>
+			<key>ID</key>
+			<string>128</string>
+			<key>Name</key>
+			<string>LPic</string>
+		</dict>
+	</array>
+	<key>styl</key>
+	<array>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>
+			AAMAAAAAAAwACQAUAAAAAAAAAAAAAAAAACcADAAJABQBAAAAAAAA
+			AAAAAAAAKgAMAAkAFAAAAAAAAAAAAAA=
+			</data>
+			<key>ID</key>
+			<string>5000</string>
+			<key>Name</key>
+			<string>English</string>
+		</dict>
+	</array>
+</dict>
+</plist>