diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d7c446fd0..f7f10463a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -353,6 +353,56 @@ jobs: path: app.tar if-no-files-found: error +# +# macOS Cryptomator.dmg +# + + mac-dmg: + name: Build Cryptomator.dmg + runs-on: macos-latest + needs: [mac-app, metadata] + steps: + - uses: actions/checkout@v2 + - name: Download mac-appdir + uses: actions/download-artifact@v2 + with: + name: mac-app + - name: Untar app.tar + run: tar -xvf app.tar + - name: Prepare .dmg contents + run: | + mkdir dmg + mv Cryptomator.app dmg + cp dist/mac/dmg/resources/macFUSE.webloc dmg + ls -l dmg + - name: Create .dmg + run: > + dist/mac/dmg/tools/create-dmg/create-dmg.sh + --volname Cryptomator + --volicon "dist/mac/dmg/resources/Cryptomator-Volume.icns" + --background "dist/mac/dmg/resources/Cryptomator-background.tiff" + --window-pos 400 100 + --window-size 640 694 + --icon-size 128 + --icon "Cryptomator.app" 128 245 + --hide-extension "Cryptomator.app" + --icon "macFUSE.webloc" 320 501 + --hide-extension "macFUSE.webloc" + --app-drop-link 512 245 + --eula "dist/mac/dmg/resources/license.rtf" + --icon ".background" 128 758 + --icon ".fseventsd" 320 758 + --icon ".VolumeIcon.icns" 512 758 + Cryptomator-${VERSION_NO}.dmg dmg + env: + VERSION_NO: ${{ needs.metadata.outputs.versionNum }} + - name: Upload mac-dmg + uses: actions/upload-artifact@v2 + with: + name: mac-dmg + path: Cryptomator-*.dmg + if-no-files-found: error + # # MSI package # diff --git a/dist/mac/dmg/resources/Cryptomator-Volume.icns b/dist/mac/dmg/resources/Cryptomator-Volume.icns new file mode 100644 index 000000000..92c362d56 Binary files /dev/null and b/dist/mac/dmg/resources/Cryptomator-Volume.icns differ diff --git a/dist/mac/dmg/resources/Cryptomator-background.tiff b/dist/mac/dmg/resources/Cryptomator-background.tiff new file mode 100644 index 000000000..c93c9a82d Binary files /dev/null and b/dist/mac/dmg/resources/Cryptomator-background.tiff differ diff --git a/dist/mac/dmg/resources/license.rtf b/dist/mac/dmg/resources/license.rtf new file mode 100644 index 000000000..ae2b7ece4 --- /dev/null +++ b/dist/mac/dmg/resources/license.rtf @@ -0,0 +1,100 @@ +{\rtf1\ansi\ansicpg1252\cocoartf2512 +\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica-Bold;\f1\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +{\*\expandedcolortbl;;} +\paperw11900\paperh16840\vieww12000\viewh15840\viewkind0 +\deftab720 +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\partightenfactor0 + +\f0\b\fs24 \cf0 Cryptomator is distributed under the GPLv3 License, found below. Please see the bottom of this document for any other license applicable to code used within Cryptomator. +\f1\b0 \ +\ + +\f0\b \'a9 2016 \'96 2021 Skymatic GmbH +\f1\b0 \ +\ +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\ +\ +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\ +\ +You should have received a copy of the GNU General Public License along with this program. If not, see {\field{\*\fldinst{HYPERLINK "http://www.gnu.org/licenses/"}}{\fldrslt http://www.gnu.org/licenses/}}.\ +\ + +\f0\b Cryptomator uses 49 third-party dependencies under the following licenses: +\f1\b0 \ + Apache License v2.0:\ + - jffi (com.github.jnr:jffi:1.2.23 - {\field{\*\fldinst{HYPERLINK "http://github.com/jnr/jffi"}}{\fldrslt http://github.com/jnr/jffi}})\ + - jnr-a64asm (com.github.jnr:jnr-a64asm:1.0.0 - {\field{\*\fldinst{HYPERLINK "http://nexus.sonatype.org/oss-repository-hosting.html/jnr-a64asm"}}{\fldrslt http://nexus.sonatype.org/oss-repository-hosting.html/jnr-a64asm}})\ + - jnr-constants (com.github.jnr:jnr-constants:0.9.15 - {\field{\*\fldinst{HYPERLINK "http://github.com/jnr/jnr-constants"}}{\fldrslt http://github.com/jnr/jnr-constants}})\ + - jnr-ffi (com.github.jnr:jnr-ffi:2.1.12 - {\field{\*\fldinst{HYPERLINK "http://github.com/jnr/jnr-ffi"}}{\fldrslt http://github.com/jnr/jnr-ffi}})\ + - FindBugs-jsr305 (com.google.code.findbugs:jsr305:3.0.2 - {\field{\*\fldinst{HYPERLINK "http://findbugs.sourceforge.net/"}}{\fldrslt http://findbugs.sourceforge.net/}})\ + - Gson (com.google.code.gson:gson:2.8.6 - {\field{\*\fldinst{HYPERLINK "https://github.com/google/gson/gson"}}{\fldrslt https://github.com/google/gson/gson}})\ + - Dagger (com.google.dagger:dagger:2.29.1 - {\field{\*\fldinst{HYPERLINK "https://github.com/google/dagger"}}{\fldrslt https://github.com/google/dagger}})\ + - error-prone annotations (com.google.errorprone:error_prone_annotations:2.3.4 - {\field{\*\fldinst{HYPERLINK "http://nexus.sonatype.org/oss-repository-hosting.html/error_prone_parent/error_prone_annotation"}}{\fldrslt http://nexus.sonatype.org/oss-repository-hosting.html/error_prone_parent/error_prone_annotation}} )\ + - Guava InternalFutureFailureAccess and InternalFutures (com.google.guava:failureaccess:1.0.1 - {\field{\*\fldinst{HYPERLINK "https://github.com/google/guava/failureaccess"}}{\fldrslt https://github.com/google/guava/failureaccess}})\ + - Guava: Google Core Libraries for Java (com.google.guava:guava:30.0-jre - {\field{\*\fldinst{HYPERLINK "https://github.com/google/guava/guava"}}{\fldrslt https://github.com/google/guava/guava}})\ + - Guava ListenableFuture only (com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava - {\field{\*\fldinst{HYPERLINK "https://github.com/google/guava/listenablefuture"}}{\fldrslt https://github.com/google/guava/listenablefuture}})\ + - J2ObjC Annotations (com.google.j2objc:j2objc-annotations:1.3 - {\field{\*\fldinst{HYPERLINK "https://github.com/google/j2objc/"}}{\fldrslt https://github.com/google/j2objc/}})\ + - Apache Commons CLI (commons-cli:commons-cli:1.4 - {\field{\*\fldinst{HYPERLINK "http://commons.apache.org/proper/commons-cli/"}}{\fldrslt http://commons.apache.org/proper/commons-cli/}})\ + - javax.inject (javax.inject:javax.inject:1 - {\field{\*\fldinst{HYPERLINK "http://code.google.com/p/atinject/"}}{\fldrslt http://code.google.com/p/atinject/}})\ + - Java Native Access (net.java.dev.jna:jna:5.6.0 - {\field{\*\fldinst{HYPERLINK "https://github.com/java-native-access/jna"}}{\fldrslt https://github.com/java-native-access/jna}})\ + - Java Native Access Platform (net.java.dev.jna:jna-platform:5.5.0 - {\field{\*\fldinst{HYPERLINK "https://github.com/java-native-access/jna"}}{\fldrslt https://github.com/java-native-access/jna}})\ + - Apache Commons Lang (org.apache.commons:commons-lang3:3.11 - {\field{\*\fldinst{HYPERLINK "https://commons.apache.org/proper/commons-lang/"}}{\fldrslt https://commons.apache.org/proper/commons-lang/}})\ + - Apache HttpCore (org.apache.httpcomponents:httpcore:4.4.13 - {\field{\*\fldinst{HYPERLINK "http://hc.apache.org/httpcomponents-core-ga"}}{\fldrslt http://hc.apache.org/httpcomponents-core-ga}})\ + - Jackrabbit WebDAV Library (org.apache.jackrabbit:jackrabbit-webdav:2.21.3 - {\field{\*\fldinst{HYPERLINK "http://jackrabbit.apache.org/jackrabbit-webdav/"}}{\fldrslt http://jackrabbit.apache.org/jackrabbit-webdav/}})\ + - Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-http"}}{\fldrslt https://eclipse.org/jetty/jetty-http}})\ + - Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-io"}}{\fldrslt https://eclipse.org/jetty/jetty-io}})\ + - Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-security"}}{\fldrslt https://eclipse.org/jetty/jetty-security}})\ + - Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-server"}}{\fldrslt https://eclipse.org/jetty/jetty-server}})\ + - Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-servlet"}}{\fldrslt https://eclipse.org/jetty/jetty-servlet}})\ + - Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-util"}}{\fldrslt https://eclipse.org/jetty/jetty-util}})\ + - Jetty :: Utilities :: Ajax(JSON) (org.eclipse.jetty:jetty-util-ajax:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-util-ajax"}}{\fldrslt https://eclipse.org/jetty/jetty-util-ajax}})\ + - Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-webapp"}}{\fldrslt https://eclipse.org/jetty/jetty-webapp}})\ + - Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-xml"}}{\fldrslt https://eclipse.org/jetty/jetty-xml}})\ + BSD:\ + - asm (org.ow2.asm:asm:7.1 - {\field{\*\fldinst{HYPERLINK "http://asm.ow2.org/"}}{\fldrslt http://asm.ow2.org/}})\ + - asm-analysis (org.ow2.asm:asm-analysis:7.1 - {\field{\*\fldinst{HYPERLINK "http://asm.ow2.org/"}}{\fldrslt http://asm.ow2.org/}})\ + - asm-commons (org.ow2.asm:asm-commons:7.1 - {\field{\*\fldinst{HYPERLINK "http://asm.ow2.org/"}}{\fldrslt http://asm.ow2.org/}})\ + - asm-tree (org.ow2.asm:asm-tree:7.1 - {\field{\*\fldinst{HYPERLINK "http://asm.ow2.org/"}}{\fldrslt http://asm.ow2.org/}})\ + - asm-util (org.ow2.asm:asm-util:7.1 - {\field{\*\fldinst{HYPERLINK "http://asm.ow2.org/"}}{\fldrslt http://asm.ow2.org/}})\ + Eclipse Public License - Version 1.0:\ + - Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-http"}}{\fldrslt https://eclipse.org/jetty/jetty-http}})\ + - Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-io"}}{\fldrslt https://eclipse.org/jetty/jetty-io}})\ + - Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-security"}}{\fldrslt https://eclipse.org/jetty/jetty-security}})\ + - Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-server"}}{\fldrslt https://eclipse.org/jetty/jetty-server}})\ + - Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-servlet"}}{\fldrslt https://eclipse.org/jetty/jetty-servlet}})\ + - Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-util"}}{\fldrslt https://eclipse.org/jetty/jetty-util}})\ + - Jetty :: Utilities :: Ajax(JSON) (org.eclipse.jetty:jetty-util-ajax:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-util-ajax"}}{\fldrslt https://eclipse.org/jetty/jetty-util-ajax}})\ + - Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-webapp"}}{\fldrslt https://eclipse.org/jetty/jetty-webapp}})\ + - Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.35.v20201120 - {\field{\*\fldinst{HYPERLINK "https://eclipse.org/jetty/jetty-xml"}}{\fldrslt https://eclipse.org/jetty/jetty-xml}})\ + Eclipse Public License - v 2.0:\ + - jnr-posix (com.github.jnr:jnr-posix:3.0.54 - {\field{\*\fldinst{HYPERLINK "http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix"}}{\fldrslt http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix}})\ + GPLv2:\ + - jnr-posix (com.github.jnr:jnr-posix:3.0.54 - {\field{\*\fldinst{HYPERLINK "http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix"}}{\fldrslt http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix}})\ + GPLv2+CE:\ + - Java Servlet API (javax.servlet:javax.servlet-api:3.1.0 - {\field{\*\fldinst{HYPERLINK "http://servlet-spec.java.net"}}{\fldrslt http://servlet-spec.java.net}})\ + - javafx-base (org.openjfx:javafx-base:15 - {\field{\*\fldinst{HYPERLINK "https://openjdk.java.net/projects/openjfx/javafx-base/"}}{\fldrslt https://openjdk.java.net/projects/openjfx/javafx-base/}})\ + - javafx-controls (org.openjfx:javafx-controls:15 - {\field{\*\fldinst{HYPERLINK "https://openjdk.java.net/projects/openjfx/javafx-controls/"}}{\fldrslt https://openjdk.java.net/projects/openjfx/javafx-controls/}})\ + - javafx-fxml (org.openjfx:javafx-fxml:15 - {\field{\*\fldinst{HYPERLINK "https://openjdk.java.net/projects/openjfx/javafx-fxml/"}}{\fldrslt https://openjdk.java.net/projects/openjfx/javafx-fxml/}})\ + - javafx-graphics (org.openjfx:javafx-graphics:15 - {\field{\*\fldinst{HYPERLINK "https://openjdk.java.net/projects/openjfx/javafx-graphics/"}}{\fldrslt https://openjdk.java.net/projects/openjfx/javafx-graphics/}})\ + LGPL 2.1:\ + - jnr-posix (com.github.jnr:jnr-posix:3.0.54 - {\field{\*\fldinst{HYPERLINK "http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix"}}{\fldrslt http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix}})\ + - Java Native Access (net.java.dev.jna:jna:5.6.0 - https://github.com/java-native-access/jna)\ + - Java Native Access Platform (net.java.dev.jna:jna-platform:5.5.0 - {\field{\*\fldinst{HYPERLINK "https://github.com/java-native-access/jna"}}{\fldrslt https://github.com/java-native-access/jna}})\ + MIT License:\ + - java jwt (com.auth0:java-jwt:3.12.0 - {\field{\*\fldinst{HYPERLINK "https://github.com/auth0/java-jwt"}}{\fldrslt https://github.com/auth0/java-jwt}})\ + - jnr-x86asm (com.github.jnr:jnr-x86asm:1.0.2 - {\field{\*\fldinst{HYPERLINK "http://github.com/jnr/jnr-x86asm"}}{\fldrslt http://github.com/jnr/jnr-x86asm}})\ + - jnr-fuse (com.github.serceman:jnr-fuse:0.5.4 - no url defined)\ + - zxcvbn4j (com.nulab-inc:zxcvbn:1.3.0 - {\field{\*\fldinst{HYPERLINK "https://github.com/nulab/zxcvbn4j"}}{\fldrslt https://github.com/nulab/zxcvbn4j}})\ + - Checker Qual (org.checkerframework:checker-qual:3.5.0 - {\field{\*\fldinst{HYPERLINK "https://checkerframework.org"}}{\fldrslt https://checkerframework.org}})\ + - SLF4J API Module (org.slf4j:slf4j-api:1.7.30 - {\field{\*\fldinst{HYPERLINK "http://www.slf4j.org"}}{\fldrslt http://www.slf4j.org}})\ + The BSD 2-Clause License:\ + - EasyBind (com.tobiasdiez:easybind:2.1.0 - {\field{\*\fldinst{HYPERLINK "https://github.com/tobiasdiez/EasyBind"}}{\fldrslt https://github.com/tobiasdiez/EasyBind}})\ +\ + +\f0\b Cryptomator uses other third-party assets under the following licenses: +\f1\b0 \ + SIL OFL 1.1 License:\ + - Font Awesome 5.12.0 ({\field{\*\fldinst{HYPERLINK "https://fontawesome.com/"}}{\fldrslt https://fontawesome.com/}})\ +\ +} \ No newline at end of file diff --git a/dist/mac/dmg/resources/macFUSE.webloc b/dist/mac/dmg/resources/macFUSE.webloc new file mode 100644 index 000000000..f149ff5b6 --- /dev/null +++ b/dist/mac/dmg/resources/macFUSE.webloc @@ -0,0 +1,8 @@ + + + + + URL + https://osxfuse.github.io/ + + diff --git a/dist/mac/dmg/tools/create-dmg/LICENSE b/dist/mac/dmg/tools/create-dmg/LICENSE new file mode 100644 index 000000000..349b6d82b --- /dev/null +++ b/dist/mac/dmg/tools/create-dmg/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2008-2014 Andrey Tarantsov + +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. diff --git a/dist/mac/dmg/tools/create-dmg/create-dmg.sh b/dist/mac/dmg/tools/create-dmg/create-dmg.sh new file mode 100755 index 000000000..299b01f60 --- /dev/null +++ b/dist/mac/dmg/tools/create-dmg/create-dmg.sh @@ -0,0 +1,422 @@ +#!/bin/bash + +# Create a read-only disk image of the contents of a folder + +set -e; + +function pure_version() { + echo '1.0.0.6' +} + +function version() { + echo "create-dmg $(pure_version)" +} + +function usage() { + version + echo "Creates a fancy DMG file." + echo "Usage: $(basename $0) [options] " + 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)" + echo " --volicon icon.icns" + echo " set volume icon" + echo " --background pic.png" + echo " set folder background image (provide png, gif, jpg)" + echo " --window-pos x y" + echo " set position the folder window" + echo " --window-size width height" + echo " set size of the folder window" + echo " --text-size text_size" + echo " set window text size (10-16)" + echo " --icon-size icon_size" + echo " set window icons size (up to 128)" + echo " --icon file_name x y" + 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" + echo " make a drop link to user QuickLook install dir, at location x,y" + echo " --eula eula_file" + echo " attach a license file to the dmg" + echo " --no-internet-enable" + echo " disable automatic mount©" + echo " --format" + echo " specify the final image format (default is UDZO)" + echo " --add-file target_name path_to_source_file x y" + echo " add additional file (option can be used multiple times)" + echo " --add-folder target_name path_to_source_folder x y" + echo " add additional folder (option can be used multiple times)" + echo " --disk-image-size x" + echo " set the disk image size manually to x MB" + echo " --hdiutil-verbose" + echo " execute hdiutil in verbose mode" + 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 " --version show tool version number" + echo " -h, --help display this help" + exit 0 +} + +WINX=10 +WINY=60 +WINW=500 +WINH=350 +ICON_SIZE=128 +TEXT_SIZE=16 +FORMAT="UDZO" +ADD_FILE_SOURCES=() +ADD_FILE_TARGETS=() +ADD_FOLDER_SOURCES=() +ADD_FOLDER_TARGETS=() +IMAGEKEY="" +HDIUTIL_VERBOSITY="" +SANDBOX_SAFE=0 +SKIP_JENKINS=0 + +while test "${1:0:1}" = "-"; do + case $1 in + --volname) + VOLUME_NAME="$2" + shift; shift;; + --volicon) + VOLUME_ICON_FILE="$2" + shift; shift;; + --background) + BACKGROUND_FILE="$2" + 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;; + --icon-size) + ICON_SIZE="$2" + shift; shift;; + --text-size) + TEXT_SIZE="$2" + shift; shift;; + --window-pos) + WINX=$2; WINY=$3 + shift; shift; shift;; + --window-size) + WINW=$2; WINH=$3 + shift; shift; shift;; + --icon) + POSITION_CLAUSE="${POSITION_CLAUSE}set position of item \"$2\" to {$3, $4} + " + shift; shift; shift; shift;; + --hide-extension) + 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) + version; exit 0;; + --pure-version) + pure_version; exit 0;; + --ql-drop-link) + QL_LINK=$2 + QL_CLAUSE="set position of item \"QuickLook\" to {$2, $3} + " + shift; shift; shift;; + --app-drop-link) + APPLICATION_LINK=$2 + APPLICATION_CLAUSE="set position of item \"Applications\" to {$2, $3} + " + shift; shift; shift;; + --eula) + EULA_RSRC=$2 + shift; shift;; + --no-internet-enable) + NOINTERNET=1 + shift;; + --format) + FORMAT="$2" + shift; shift;; + --add-file) + ADD_FILE_TARGETS+=("$2") + ADD_FILE_SOURCES+=("$3") + POSITION_CLAUSE="${POSITION_CLAUSE} + set position of item \"$2\" to {$4, $5} + " + shift; shift; shift; shift; shift;; + --add-folder) + ADD_FOLDER_TARGETS+=("$2") + ADD_FOLDER_SOURCES+=("$3") + POSITION_CLAUSE="${POSITION_CLAUSE} + set position of item \"$2\" to {$4, $5} + " + shift; shift; shift; shift; shift;; + --disk-image-size) + DISK_IMAGE_SIZE="$2" + shift; shift;; + --hdiutil-verbose) + HDIUTIL_VERBOSITY='-verbose' + shift;; + --hdiutil-quiet) + HDIUTIL_VERBOSITY='-quiet' + shift;; + --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." + exit 1;; + esac + case $FORMAT in + UDZO) + IMAGEKEY="-imagekey zlib-level=9";; + UDBZ) + IMAGEKEY="-imagekey bzip2-level=9";; + esac +done + +test -z "$2" && { + echo "Not enough arguments. Invoke with --help for help." + exit 1 +} + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +DMG_PATH="$1" +DMG_DIRNAME="$(dirname "$DMG_PATH")" +DMG_DIR="$(cd "$DMG_DIRNAME" > /dev/null; pwd)" +DMG_NAME="$(basename "$DMG_PATH")" +DMG_TEMP_NAME="$DMG_DIR/rw.${DMG_NAME}" +SRC_FOLDER="$(cd "$2" > /dev/null; pwd)" + +test -z "$VOLUME_NAME" && VOLUME_NAME="$(basename "$DMG_PATH" .dmg)" + +# brew formula will set this as 1 and embed the support scripts +BREW_INSTALL=0 + +AUX_PATH="$SCRIPT_DIR/support" + +if [ $BREW_INSTALL -eq 0 ]; then + test -d "$AUX_PATH" || { + echo "Cannot find support directory: $AUX_PATH" + exit 1 + } +fi + +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}" + +# Using Megabytes since hdiutil fails with very large Byte numbers +function blocks_to_megabytes() { + # Add 1 extra MB, since there's no decimal retention here + MB_SIZE=$((($1 * 512 / 1000 / 1000) + 1)) + echo $MB_SIZE +} + +function get_size() { + # Get block size in disk + 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 ! test -z "$DISK_IMAGE_SIZE"; then + CUSTOM_SIZE="-size ${DISK_IMAGE_SIZE}m" +fi + +if [ $SANDBOX_SAFE -eq 0 ]; then + hdiutil create ${HDIUTIL_VERBOSITY} -srcfolder "$SRC_FOLDER" -volname "${VOLUME_NAME}" -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW ${CUSTOM_SIZE} "${DMG_TEMP_NAME}" +else + hdiutil makehybrid ${HDIUTIL_VERBOSITY} -default-volume-name "${VOLUME_NAME}" -hfs -o "${DMG_TEMP_NAME}" "$SRC_FOLDER" + hdiutil convert -format UDRW -ov -o "${DMG_TEMP_NAME}" "${DMG_TEMP_NAME}" + DISK_IMAGE_SIZE_CUSTOM=$DISK_IMAGE_SIZE +fi + +# Get the created DMG actual size +DISK_IMAGE_SIZE=`get_size "${DMG_TEMP_NAME}"` + +# Use the custom size if bigger +if [ $SANDBOX_SAFE -eq 1 ] && [ ! -z "$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 ! test -z "$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 +if ! test -z "$ADD_FOLDER_SOURCES"; then + for i in "${!ADD_FOLDER_SOURCES[@]}" + do + SOURCE_SIZE=`get_size "${ADD_FOLDER_SOURCES[$i]}"` + DISK_IMAGE_SIZE=$(expr $DISK_IMAGE_SIZE + $SOURCE_SIZE) + done +fi + +# Add extra space for additional resources +DISK_IMAGE_SIZE=$(expr $DISK_IMAGE_SIZE + 20) + +# Resize the image for the extra stuff +hdiutil resize ${HDIUTIL_VERBOSITY} -size ${DISK_IMAGE_SIZE}m "${DMG_TEMP_NAME}" + +# mount it +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) +echo "Unmounting disk image..." +DEV_NAME=$(hdiutil info | egrep --color=never '^/dev/' | sed 1q | awk '{print $1}') +test -d "${MOUNT_DIR}" && hdiutil detach "${DEV_NAME}" + +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 ! test -z "$BACKGROUND_FILE"; then + echo "Copying background file..." + test -d "$MOUNT_DIR/.background" || mkdir "$MOUNT_DIR/.background" + cp "$BACKGROUND_FILE" "$MOUNT_DIR/.background/$BACKGROUND_FILE_NAME" +fi + +if ! test -z "$APPLICATION_LINK"; then + echo "making link to Applications dir" + echo $MOUNT_DIR + ln -s /Applications "$MOUNT_DIR/Applications" +fi + +if ! test -z "$QL_LINK"; then + echo "making link to QuickLook install dir" + echo $MOUNT_DIR + ln -s "/Library/QuickLook" "$MOUNT_DIR/QuickLook" +fi + +if ! test -z "$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 ! test -z "$ADD_FILE_SOURCES"; then + echo "Copying custom files..." + 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 + +if ! test -z "$ADD_FOLDER_SOURCES"; then + echo "Copying custom folders..." + for i in "${!ADD_FOLDER_SOURCES[@]}" + do + echo "${ADD_FOLDER_SOURCES[$i]}" + cp -a "${ADD_FOLDER_SOURCES[$i]}" "$MOUNT_DIR/${ADD_FOLDER_TARGETS[$i]}" + done +fi + +# run applescript +APPLESCRIPT=$(mktemp -t createdmg.tmp.XXXXXXXXXX) + +function applescript_source() { + if [ $BREW_INSTALL -eq 0 ]; then + cat "$AUX_PATH/template.applescript" + else + cat << 'EOS' + # BREW_INLINE_APPLESCRIPT_PLACEHOLDER +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" +fi + +# make sure it's not world writeable +echo "Fixing permissions..." +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 + echo "Blessing started" + bless --folder "${MOUNT_DIR}" --openfolder "${MOUNT_DIR}" + echo "Blessing finished" +else + echo "Skipping blessing on sandbox" +fi + +if ! test -z "$VOLUME_ICON_FILE"; then + # tell the volume that it has a special file attribute + SetFile -a C "$MOUNT_DIR" +fi + +# unmount +echo "Unmounting disk image..." +hdiutil detach "${DEV_NAME}" + +# compress image +echo "Compressing disk image..." +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}" -a "${EULA_RSRC}" != "-null-" ]; then + echo "adding EULA resources" + + REZ_ARG="" + if [ ! -z "${REZ_PATH}" -a "${REZ_PATH}" != "-null-" ]; 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} + else + python - "${DMG_DIR}/${DMG_NAME}" "${EULA_RSRC}" ${REZ_ARG} <<-'EOS' + # BREW_INLINE_LICENSE_PLACEHOLDER +EOS + fi +fi + +if [ ! -z "${NOINTERNET}" -a "${NOINTERNET}" == 1 ]; then + echo "not setting 'internet-enable' on the dmg" +else + # check if hdiutil supports internet-enable + # support was removed in macOS 10.15 + # https://github.com/andreyvit/create-dmg/issues/76 + if hdiutil internet-enable -help >/dev/null 2>/dev/null + then + hdiutil internet-enable -yes "${DMG_DIR}/${DMG_NAME}" + else + echo "hdiutil does not support internet-enable. Note it was removed in macOS 10.15." + fi +fi + +echo "Disk image done" +exit 0 diff --git a/dist/mac/dmg/tools/create-dmg/support/dmg-license.py b/dist/mac/dmg/tools/create-dmg/support/dmg-license.py new file mode 100755 index 000000000..edf04ee6b --- /dev/null +++ b/dist/mac/dmg/tools/create-dmg/support/dmg-license.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python +""" +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 + + +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 [OPTIONS] + This program adds a software license agreement to a DMG file. + It requires Xcode and either a plain ascii text + or a with the RTF contents. + + See --help for more details.""") + parser.add_option( + '--rez', + '-r', + action='store', + default='/Applications/Xcode.app/Contents/Developer/Tools/Rez', + 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"!\n' % options.rez) + cond = True + if cond: + parser.print_usage() + sys.exit(1) + main(options, args) diff --git a/dist/mac/dmg/tools/create-dmg/support/template.applescript b/dist/mac/dmg/tools/create-dmg/support/template.applescript new file mode 100644 index 000000000..fee634d31 --- /dev/null +++ b/dist/mac/dmg/tools/create-dmg/support/template.applescript @@ -0,0 +1,74 @@ +on run (volumeName) + tell application "Finder" + tell disk (volumeName as string) + open + + set theXOrigin to WINX + set theYOrigin to WINY + set theWidth to WINW + set theHeight to WINH + + set theBottomRightX to (theXOrigin + theWidth) + set theBottomRightY to (theYOrigin + theHeight) + set dsStore to "\"" & "/Volumes/" & volumeName & "/" & ".DS_STORE\"" + + tell container window + set current view to icon view + set toolbar visible to false + set statusbar visible to false + set the bounds to {theXOrigin, theYOrigin, theBottomRightX, theBottomRightY} + set statusbar visible to false + REPOSITION_HIDDEN_FILES_CLAUSE + end tell + + set opts to the icon view options of container window + tell opts + set icon size to ICON_SIZE + set text size to TEXT_SIZE + set arrangement to not arranged + end tell + BACKGROUND_CLAUSE + + -- Positioning + POSITION_CLAUSE + + -- Hiding + HIDING_CLAUSE + + -- Application and QL Link Clauses + APPLICATION_CLAUSE + QL_CLAUSE + close + open + -- Force saving of the size + delay 1 + + tell container window + set statusbar visible to false + set the bounds to {theXOrigin, theYOrigin, theBottomRightX - 10, theBottomRightY - 10} + end tell + end tell + + delay 1 + + tell disk (volumeName as string) + tell container window + set statusbar visible to false + set the bounds to {theXOrigin, theYOrigin, theBottomRightX, theBottomRightY} + end tell + end tell + + --give the finder some time to write the .DS_Store file + delay 3 + + set waitTime to 0 + set ejectMe to false + repeat while ejectMe is false + delay 1 + set waitTime to waitTime + 1 + + if (do shell script "[ -f " & dsStore & " ]; echo $?") = "0" then set ejectMe to true + end repeat + log "waited " & waitTime & " seconds for .DS_STORE to be created." + end tell +end run