Update create-dmg to 1.1.0 to work with Apple Silicon Macs

This commit is contained in:
Yee Cheng Chin
2022-07-25 04:40:39 -07:00
parent 6b7373168d
commit aeafa394bd
11 changed files with 307 additions and 257 deletions

View File

@@ -0,0 +1,19 @@
# EditorConfig for create-dmg project
# EditorConfig is awesome: https://EditorConfig.org
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
# We use tabs in our own code
[{create-dmg,*.applescript,*.sh}]
indent_style = tab
indent_size = 2
# But the Python code we pull in from pyhacker uses spaces
[*.py]
indent_style = space
indent_size = 4

5
src/create-dmg/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
.svn
.vscode
*.dmg
.DS_Store

View File

@@ -0,0 +1,2 @@
This is just a dummy file so create-dmg can tell whether it's being run from
inside the Git repo or from an installed location.

33
src/create-dmg/Makefile Normal file
View File

@@ -0,0 +1,33 @@
# Makefile for Cowsay
PACKAGE_TARNAME = create-dmg
prefix = /usr/local
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
datarootdir = ${prefix}/share
datadir = ${datarootdir}
docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
sysconfdir = ${prefix}/etc
mandir=${datarootdir}/man
srcdir = .
SHELL = /bin/sh
INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_DATA = ${INSTALL} -m 644
.PHONY: install uninstall
install: create-dmg
$(INSTALL) -d $(DESTDIR)$(prefix)
$(INSTALL) -d $(DESTDIR)$(bindir)
$(INSTALL_PROGRAM) create-dmg $(DESTDIR)$(bindir)/create-dmg
$(INSTALL) -d $(DESTDIR)$(datadir)/$(PACKAGE_TARNAME)
cp -R support $(DESTDIR)$(datadir)/$(PACKAGE_TARNAME)
cp -R examples $(DESTDIR)$(datadir)/$(PACKAGE_TARNAME)
cp -R tests $(DESTDIR)$(datadir)/$(PACKAGE_TARNAME)
uninstall:
rm -f $(DESTDIR)$(bindir)/create-dmg
rm -rf $(DESTDIR)$(datadir)/$(PACKAGE_TARNAME)

View File

@@ -1 +1 @@
Content of this directory is copied from https://github.com/create-dmg/create-dmg (v1.0.8 / 0985398).
Content of this directory is copied from https://github.com/create-dmg/create-dmg (v1.1.0 / 48a4aadb768da76e7903d090f31a2db20c583942).

View File

@@ -6,8 +6,7 @@ A shell script to build fancy DMGs.
Status and contribution policy
------------------------------
Create-dmg is maintained thanks to the contributors who send pull requests.
As of May 2020, [Andrew Janke](https://github.com/apjanke) is the primary maintainer, and (since September 2018) [@aonez](https://github.com/aonez) has helped with the maintenance.
Create-dmg is mostly maintained by [@aonez](https://github.com/aonez) and the contributors who send pull requests.
The project home page is <https://github.com/create-dmg/create-dmg>.
We will merge any pull request that adds something useful and does not break existing things.
@@ -15,6 +14,7 @@ We will merge any pull request that adds something useful and does not break exi
If you're an active user and want to be a maintainer, or just want to chat, please ping us on Gitter at [gitter.im/create-dmg/Lobby](https://gitter.im/create-dmg/Lobby), or [email Andrew directly](floss@apjanke.net).
Create-dmg was originally created by [Andrey Tarantsov](https://github.com/andreyvit).
In May 2020 [Andrew Janke](https://github.com/apjanke) helped vastly with the project.
Installation
------------
@@ -63,12 +63,17 @@ All contents of source\_folder will be copied into the disk image.
- **--eula \<eula_file\>:** attach a license file to the dmg
- **--rez \<rez_path\>:** specify custom path to Rez tool used to include license file
- **--no-internet-enable:** disable automatic mount&copy
- **--format:** specify the final image format (default is UDZO)
- **--format:** specify the final image format (UDZO|UDBZ|ULFO|ULMO) (default is UDZO)
- **--add-file \<target_name\> \<file|folder\> \<x\> \<y\>:** add additional file or folder (can be used multiple times)
- **--disk-image-size \<x\>:** set the disk image size manually to x MB
- **--hdiutil-verbose:** execute hdiutil in verbose mode
- **--hdiutil-quiet:** execute hdiutil in quiet mode
- **--sandbox-safe:** execute hdiutil with sandbox compatibility and do not bless
- **--bless:** bless the mount folder (deprecated, needs macOS 12.2.1 or older, [#127](https://github.com/create-dmg/create-dmg/pull/127))
- **--codesign \<signature\>:** codesign the disk image with the specified signature
- **--notarize \<credentials>:** notarize the disk image (waits and staples) with the keychain stored credentials
For more information check [Apple's documentation](https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow)
- **--skip-jenkins:** skip Finder-prettifying AppleScript, useful in Sandbox and non-GUI environments, [#72](https://github.com/create-dmg/create-dmg/pull/72)
- **--sandbox-safe:** hdiutil with sandbox compatibility, do not bless and do not execute the cosmetic AppleScript
- **--version:** show tool version number
- **-h, --help:** display the help
@@ -94,6 +99,19 @@ create-dmg \
See the `examples` folder in the source tree for more examples.
Requirements
------------
Nothing except a standard installation of macOS/OS X is required.
We think this works in OS X 10.6 Snow Leopard and later.
We'd like to keep it working in as many versions as possible, but unfortunately, we just don't have test boxes running old versions of OS X adequate to make this happen. Development and testing mostly happens in the last 3-5 years' worth of macOS releases; as of 2020, this means macOS 10.12 and later.
But if you find a bug in an older version, go ahead and report it! We'll try to work with you to get it fixed.
If you're running OS X 10.5 or later, you're SOL. That's just too hard to deal with in 2020. ;)
Alternatives
------------

View File

@@ -5,7 +5,7 @@
# Bail out on any unhandled errors
set -e;
CDMG_VERSION='1.0.8'
CDMG_VERSION='1.1.0'
# The full path to the "support/" directory this script is using
# (This will be set up by code later in the script.)
@@ -23,7 +23,11 @@ ADD_FILE_TARGETS=()
IMAGEKEY=""
HDIUTIL_VERBOSITY=""
SANDBOX_SAFE=0
BLESS=0
SKIP_JENKINS=0
MAXIMUM_UNMOUNTING_ATTEMPTS=3
SIGNATURE=""
NOTARIZE=""
function pure_version() {
echo "$CDMG_VERSION"
@@ -62,8 +66,6 @@ Options:
set position of the file's icon
--hide-extension <file_name>
hide the extension of file
--custom-icon <file_name> <custom_icon_or_sample_file> <x> <y>
set position and custom icon
--app-drop-link <x> <y>
make a drop link to Applications, at location x,y
--ql-drop-link <x> <y>
@@ -73,7 +75,7 @@ Options:
--no-internet-enable
disable automatic mount & copy
--format <format>
specify the final image format (default is UDZO)
specify the final disk image format (UDZO|UDBZ|ULFO|ULMO) (default is UDZO)
--add-file <target_name> <file>|<folder> <x> <y>
add additional file or folder (can be used multiple times)
--disk-image-size <x>
@@ -82,10 +84,14 @@ Options:
execute hdiutil in verbose mode
--hdiutil-quiet
execute hdiutil in quiet mode
--bless
bless the mount folder (deprecated, needs macOS 12.2.1 or older)
--codesign <signature>
codesign the disk image with the specified signature
--notarize <credentials>
notarize the disk image (waits and staples) with the keychain stored credentials
--sandbox-safe
execute hdiutil with sandbox compatibility and do not bless
--rez <rez_path>
use custom path to Rez tool
--version
show create-dmg version number
-h, --help
@@ -131,8 +137,6 @@ while [[ "${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)
@@ -173,12 +177,21 @@ while [[ "${1:0:1}" = "-" ]]; do
shift;;
--hdiutil-quiet)
HDIUTIL_VERBOSITY='-quiet'
shift;;
shift;;
--codesign)
SIGNATURE="$2"
shift; shift;;
--notarize)
NOTARIZE="$2"
shift; shift;;
--sandbox-safe)
SANDBOX_SAFE=1
shift;;
shift;;
--bless)
BLESS=1
shift;;
--rez)
REZ_PATH="$2"
echo "REZ is no more directly used. You can remove the --rez argument."
shift; shift;;
--skip-jenkins)
SKIP_JENKINS=1
@@ -192,8 +205,12 @@ while [[ "${1:0:1}" = "-" ]]; do
IMAGEKEY="-imagekey zlib-level=9";;
UDBZ)
IMAGEKEY="-imagekey bzip2-level=9";;
ULFO)
;;
ULMO)
;;
*)
echo >&2 "Unknown format: $FORMAT"
echo >&2 "Unknown disk image format: $FORMAT"
exit 1;;
esac
done
@@ -206,6 +223,13 @@ fi
DMG_PATH="$1"
SRC_FOLDER="$(cd "$2" > /dev/null; pwd)"
# 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
# Main script logic
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
@@ -283,7 +307,7 @@ if [[ $SANDBOX_SAFE -eq 1 ]] && [[ ! -z "$DISK_IMAGE_SIZE_CUSTOM" ]] && [[ $DISK
DISK_IMAGE_SIZE=$DISK_IMAGE_SIZE_CUSTOM
fi
# Estimate the additional soruces size
# 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]}")
@@ -294,6 +318,12 @@ 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}"
@@ -304,18 +334,18 @@ MOUNT_DIR="/Volumes/${VOLUME_NAME}"
# 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 old disk image from $MOUNT_DIR..."
DEV_NAME=$(hdiutil info | egrep --color=never '^/dev/' | sed 1q | awk '{print $1}')
DEV_NAME=$(hdiutil info | grep -E --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}')
DEV_NAME=$(hdiutil attach -readwrite -noverify -noautoopen "${DMG_TEMP_NAME}" | grep -E --color=never '^/dev/' | sed 1q | awk '{print $1}')
echo "Device name: $DEV_NAME"
if [[ -n "$BACKGROUND_FILE" ]]; then
echo "Copying background file..."
echo "Copying background file '$BACKGROUND_FILE'..."
[[ -d "$MOUNT_DIR/.background" ]] || mkdir "$MOUNT_DIR/.background"
cp "$BACKGROUND_FILE" "$MOUNT_DIR/.background/$BACKGROUND_FILE_NAME"
fi
@@ -384,7 +414,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 [[ $BLESS -eq 1 && $SANDBOX_SAFE -eq 0 ]]; then
echo "Blessing started"
bless --folder "${MOUNT_DIR}" --openfolder "${MOUNT_DIR}"
echo "Blessing finished"
@@ -397,9 +427,27 @@ if [[ -n "$VOLUME_ICON_FILE" ]]; then
SetFile -a C "$MOUNT_DIR"
fi
# Delete unnecessary file system events log if possible
echo "Deleting .fseventsd"
rm -rf "${MOUNT_DIR}/.fseventsd" || true
# 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..."
@@ -409,15 +457,35 @@ rm -f "${DMG_TEMP_NAME}"
# Adding EULA resources
if [[ -n "${EULA_RSRC}" && "${EULA_RSRC}" != "-null-" ]]; then
echo "Adding EULA resources..."
REZ_ARG=""
if [[ -n "${REZ_PATH}" && "${REZ_PATH}" != "-null-" ]]; then
REZ_ARG="--rez ${REZ_PATH}"
#
# 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
xcode_path=$(xcode-select -p)
default_rez="$xcode_path/Tools/Rez"
REZ_ARG="--rez ${default_rez}"
EULA_FORMAT='TEXT'
fi
"${CDMG_SUPPORT_DIR}/licenseDMG.py" "${DMG_DIR}/${DMG_NAME}" "${EULA_RSRC}" ${REZ_ARG}
# 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
$(<${CDMG_SUPPORT_DIR}/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
# Enable "internet", whatever that is
@@ -433,6 +501,32 @@ else
fi
fi
if [[ -n "${SIGNATURE}" && "${SIGNATURE}" != "-null-" ]]; then
echo "Codesign started"
codesign -s "${SIGNATURE}" "${DMG_DIR}/${DMG_NAME}"
dmgsignaturecheck="$(codesign --verify --deep --verbose=2 --strict "${DMG_DIR}/${DMG_NAME}" 2>&1 >/dev/null)"
if [ $? -eq 0 ]; then
echo "The disk image is now codesigned"
else
echo "The signature seems invalid${NC}"
exit 1
fi
fi
if [[ -n "${NOTARIZE}" && "${NOTARIZE}" != "-null-" ]]; then
echo "Notarization started"
xcrun notarytool submit "${DMG_DIR}/${DMG_NAME}" --keychain-profile "${NOTARIZE}" --wait
echo "Stapling the notarization ticket"
staple="$(xcrun stapler staple "${DMG_DIR}/${DMG_NAME}")"
if [ $? -eq 0 ]; then
echo "The disk image is now notarized"
else
echo "$staple"
echo "The notarization failed with error $?"
exit 1
fi
fi
# All done!
echo "Disk image done"
exit 0

View File

@@ -1,19 +0,0 @@
Copyright (c) 2015-2019 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.

View File

@@ -1,7 +0,0 @@
# create-dmg support files
## licenseDMG.py
The licenseDMG.py script is taken from Jared Hobbs' pyhacker library, at <https://bitbucket.org/jaredhobbs/pyhacker>.
See LICENSE-licenseDMG-pyhacker for licensing details.

View File

@@ -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>

View File

@@ -1,200 +0,0 @@
#! /usr/bin/env python
"""
This script adds a license file to a DMG. Requires Xcode and a plain ascii text
license file or an RTF license file.
Obviously only runs on a Mac.
Copyright (C) 2011-2019 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 unicode_literals
from subprocess import check_call, check_output, call, CalledProcessError
import argparse
import logging as logger
import os
import sys
import tempfile
logger.basicConfig(format='%(message)s', level=logger.DEBUG)
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 escape(s):
return s.strip().replace('\\', '\\\\').replace('"', '\\"')
def main(options):
dmg_file = options.dmg_file
output = options.output or dmg_file
license = options.license_file
if dmg_file != output:
check_call(['cp', dmg_file, output])
dmg_file = output
with mktemp('.') as tmp_file:
with open(tmp_file, '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_file:
kind = 'RTF ' if license.lower().endswith('.rtf') else 'TEXT'
f.write('data \'{}\' (5000, "English") {{\n'.format(kind))
for line in l_file:
if len(line) < 1000:
f.write(' "{}\\n"\n'.format(escape(line)))
else:
for liner in line.split('.'):
f.write(' "{}. \\n"\n'.format(escape(liner)))
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""")
call(['hdiutil', 'unflatten', '-quiet', dmg_file])
ret = check_call([options.rez, '-a', tmp_file, '-o', dmg_file])
call(['hdiutil', 'flatten', '-quiet', dmg_file])
if options.compression is not None:
tmp_dmg = '{}.temp.dmg'.format(dmg_file)
check_call(['cp', dmg_file, tmp_dmg])
os.remove(dmg_file)
args = ['hdiutil', 'convert', tmp_dmg, '-quiet', '-format']
if options.compression == 'bz2':
args.append('UDBZ')
elif options.compression == "gz":
args.extend(['UDZO', '-imagekey', 'zlib-devel=9'])
args.extend(['-o', dmg_file])
check_call(args)
os.remove(tmp_dmg)
if ret == 0:
logger.info("Successfully added license to '{}'".format(dmg_file))
else:
logger.error("Failed to add license to '{}'".format(dmg_file))
if __name__ == '__main__':
try:
rez_path = check_output(
['xcrun', '--find', 'Rez'],
).strip().decode('utf-8')
except CalledProcessError:
rez_path = '/Library/Developer/CommandLineTools/usr/bin/Rez'
parser = argparse.ArgumentParser(
description="""\
This program adds a software license agreement to a DMG file.
It requires Xcode and either a plain ascii text <license_file>
or a <license_file.rtf> with the RTF contents.
See --help for more details.""",
)
parser.add_argument(
'dmg_file',
help='the path to the dmg file which will receive the license',
)
parser.add_argument(
'license_file',
help='the path to the plain ascii or RTF license file; for RTF files, '
'the file must use a .rtf extension',
)
parser.add_argument(
'--rez',
'-r',
action='store',
default=rez_path,
help='the path to the Rez tool; defaults to %(default)s',
)
parser.add_argument(
'--compression',
'-c',
action='store',
choices=('bz2', 'gz'),
default=None,
help='optionally compress dmg using specified compression type; '
'choices are bz2 and gz',
)
parser.add_argument(
'--output',
'-o',
action='store',
default=None,
help='specify an output DMG file; if not given, the license will be '
'directly applied to the input DMG file',
)
options = parser.parse_args()
if not os.path.exists(options.rez):
logger.error('Failed to find Rez at "{}"!\n'.format(options.rez))
parser.print_usage()
sys.exit(1)
main(options)