diff --git a/Installer/OSX/Distribution.xml b/Installer/OSX/Distribution.xml new file mode 100644 index 000000000..3f770341a --- /dev/null +++ b/Installer/OSX/Distribution.xml @@ -0,0 +1,25 @@ + + + Duplicati + com.duplicati + + + + + + + + + + + + + + + + + + + DuplicatiApp.pkg + DuplicatiDaemon.pkg + \ No newline at end of file diff --git a/Installer/OSX/Duplicati-commandline-launcher b/Installer/OSX/Duplicati-commandline-launcher index 32f6ff9bc..27942befd 100644 --- a/Installer/OSX/Duplicati-commandline-launcher +++ b/Installer/OSX/Duplicati-commandline-launcher @@ -1,71 +1,7 @@ -#!/bin/sh -# -# This is a stub script that allows .apps to be relocatable on OSX but still -# find the managed assembly. -# -# This is copied from the Mono macpack tool and modified to fit Duplicati -# -# The Mono Version Check is from here: -# http://mjhutchinson.com/journal/2010/01/24/creating_mac_app_bundle_for_gtk_app -# +#!/bin/bash +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -PWD=`pwd` -# Fetch the path relative to the launch point where this shell script exists. -APP_PATH=`echo $0 | awk '{split($0,patharr,"/"); idx=1; while(patharr[idx+3] != "") { if (patharr[idx] != "/") {printf("%s/", patharr[idx]); idx++ }} }'` +export APP_NAME="Duplicati CommandLine" +export ASSEMBLY="Duplicati.CommandLine.exe" -APP_NAME="Duplicati.CommandLine" -ASSEMBLY="Duplicati.CommandLine.exe" - -export GDIPLUS_NOX=1 - -#mono version check - -REQUIRED_MAJOR=2 -REQUIRED_MINOR=8 - -VERSION_TITLE="Cannot launch $APP_NAME" -VERSION_MSG="$APP_NAME requires the Mono Framework version $REQUIRED_MAJOR.$REQUIRED_MINOR or later." -DOWNLOAD_URL="http://www.go-mono.com/mono-downloads/download.html" - -MONO_VERSION="$(mono --version | grep 'Mono JIT compiler version ' | cut -f5 -d\ )" -MONO_VERSION_MAJOR="$(echo $MONO_VERSION | cut -f1 -d.)" -MONO_VERSION_MINOR="$(echo $MONO_VERSION | cut -f2 -d.)" -if [ -z "$MONO_VERSION" ] \ - || [ $MONO_VERSION_MAJOR -lt $REQUIRED_MAJOR ] \ - || [ $MONO_VERSION_MAJOR -eq $REQUIRED_MAJOR -a $MONO_VERSION_MINOR -lt $REQUIRED_MINOR ] -then - osascript \ - -e "set question to display dialog \"$VERSION_MSG\" with title \"$VERSION_TITLE\" buttons {\"Cancel\", \"Download...\"} default button 2" \ - -e "if button returned of question is equal to \"Download...\" then open location \"$DOWNLOAD_URL\"" - echo "$VERSION_TITLE" - echo "$VERSION_MSG" - exit 1 -fi - -# Move into the folder where all the assemblies are located -cd "$APP_PATH/Contents/MonoBundle" - -# Make a symlink so Duplicati shows up as "Duplicati" in ps and not as "mono" -if [ ! -d "./bin" ]; then mkdir bin ; fi - -if [ ! -d "./bin" ] -then - # We cannot make the extra dir (most likely we are running on read-only medium) - # Instead we attempt to use exec to set the appname - OSX_VERSION=$(uname -r | cut -f1 -d.) - if [ $OSX_VERSION -lt 9 ]; then # If OSX version is 10.4 - MONO_EXEC="exec mono" - else - MONO_EXEC="exec -a \"$APP_NAME\" mono" - fi - $MONO_EXEC "$ASSEMBLY" - -else - - # We can make the helper file, lets use that - if [ -f "./bin/$APP_NAME" ]; then rm -f "./bin/$APP_NAME" ; fi - ln -s `which mono` "./bin/$APP_NAME" - - # Start Duplicati using the renamed symlink to Mono - "./bin/$APP_NAME" "$ASSEMBLY" -fi \ No newline at end of file +bash "${SCRIPT_DIR}/run-with-mono.sh" $@ \ No newline at end of file diff --git a/Installer/OSX/Duplicati-server-launcher b/Installer/OSX/Duplicati-server-launcher index 51dbdb66f..448482fee 100644 --- a/Installer/OSX/Duplicati-server-launcher +++ b/Installer/OSX/Duplicati-server-launcher @@ -1,71 +1,7 @@ -#!/bin/sh -# -# This is a stub script that allows .apps to be relocatable on OSX but still -# find the managed assembly. -# -# This is copied from the Mono macpack tool and modified to fit Duplicati -# -# The Mono Version Check is from here: -# http://mjhutchinson.com/journal/2010/01/24/creating_mac_app_bundle_for_gtk_app -# +#!/bin/bash +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -PWD=`pwd` -# Fetch the path relative to the launch point where this shell script exists. -APP_PATH=`echo $0 | awk '{split($0,patharr,"/"); idx=1; while(patharr[idx+3] != "") { if (patharr[idx] != "/") {printf("%s/", patharr[idx]); idx++ }} }'` +export APP_NAME="Duplicati Server" +export ASSEMBLY="Duplicati.Server.exe" -APP_NAME="Duplicati.Server" -ASSEMBLY="Duplicati.Server.exe" - -export GDIPLUS_NOX=1 - -#mono version check - -REQUIRED_MAJOR=2 -REQUIRED_MINOR=8 - -VERSION_TITLE="Cannot launch $APP_NAME" -VERSION_MSG="$APP_NAME requires the Mono Framework version $REQUIRED_MAJOR.$REQUIRED_MINOR or later." -DOWNLOAD_URL="http://www.go-mono.com/mono-downloads/download.html" - -MONO_VERSION="$(mono --version | grep 'Mono JIT compiler version ' | cut -f5 -d\ )" -MONO_VERSION_MAJOR="$(echo $MONO_VERSION | cut -f1 -d.)" -MONO_VERSION_MINOR="$(echo $MONO_VERSION | cut -f2 -d.)" -if [ -z "$MONO_VERSION" ] \ - || [ $MONO_VERSION_MAJOR -lt $REQUIRED_MAJOR ] \ - || [ $MONO_VERSION_MAJOR -eq $REQUIRED_MAJOR -a $MONO_VERSION_MINOR -lt $REQUIRED_MINOR ] -then - osascript \ - -e "set question to display dialog \"$VERSION_MSG\" with title \"$VERSION_TITLE\" buttons {\"Cancel\", \"Download...\"} default button 2" \ - -e "if button returned of question is equal to \"Download...\" then open location \"$DOWNLOAD_URL\"" - echo "$VERSION_TITLE" - echo "$VERSION_MSG" - exit 1 -fi - -# Move into the folder where all the assemblies are located -cd "$APP_PATH/Contents/MonoBundle" - -# Make a symlink so Duplicati shows up as "Duplicati" in ps and not as "mono" -if [ ! -d "./bin" ]; then mkdir bin ; fi - -if [ ! -d "./bin" ] -then - # We cannot make the extra dir (most likely we are running on read-only medium) - # Instead we attempt to use exec to set the appname - OSX_VERSION=$(uname -r | cut -f1 -d.) - if [ $OSX_VERSION -lt 9 ]; then # If OSX version is 10.4 - MONO_EXEC="exec mono" - else - MONO_EXEC="exec -a \"$APP_NAME\" mono" - fi - $MONO_EXEC "$ASSEMBLY" - -else - - # We can make the helper file, lets use that - if [ -f "./bin/$APP_NAME" ]; then rm -f "./bin/$APP_NAME" ; fi - ln -s `which mono` "./bin/$APP_NAME" - - # Start Duplicati using the renamed symlink to Mono - "./bin/$APP_NAME" "$ASSEMBLY" -fi \ No newline at end of file +bash "${SCRIPT_DIR}/run-with-mono.sh" $@ diff --git a/Installer/OSX/Duplicati-trayicon-launcher b/Installer/OSX/Duplicati-trayicon-launcher new file mode 100644 index 000000000..122d712aa --- /dev/null +++ b/Installer/OSX/Duplicati-trayicon-launcher @@ -0,0 +1,7 @@ +#!/bin/bash +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +export APP_NAME="Duplicati" +export ASSEMBLY="Duplicati.GUI.TrayIcon.exe" + +bash "${SCRIPT_DIR}/run-with-mono.sh" $@ \ No newline at end of file diff --git a/Installer/OSX/Info.plist b/Installer/OSX/Info.plist new file mode 100644 index 000000000..85b7ded2e --- /dev/null +++ b/Installer/OSX/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + duplicati + CFBundleIconFile + Duplicati.icns + CFBundleIdentifier + com.duplicati.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Duplicati + CFBundlePackageType + APPL + CFBundleSignature + SUBL + CFBundleVersion + !LONG_VERSION! + CFBundleDisplayName + Duplicati + CFBundleShortVersionString + !SHORT_VERSION! + LSUIElement + + + \ No newline at end of file diff --git a/Installer/OSX/InstallerComponent.plist b/Installer/OSX/InstallerComponent.plist new file mode 100644 index 000000000..5dd5da85f --- /dev/null +++ b/Installer/OSX/InstallerComponent.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/Installer/OSX/app-scripts/postinstall b/Installer/OSX/app-scripts/postinstall new file mode 100755 index 000000000..13d191177 --- /dev/null +++ b/Installer/OSX/app-scripts/postinstall @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/bin/open /Applications/Duplicati.app \ No newline at end of file diff --git a/Installer/OSX/app-scripts/preinstall b/Installer/OSX/app-scripts/preinstall new file mode 100755 index 000000000..ce357c45b --- /dev/null +++ b/Installer/OSX/app-scripts/preinstall @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e +if pgrep -x "Duplicati"; then + RES=`osascript \ + -e "set question to display dialog \"Duplicati is currently running, you should quite before installing a new version\" with title \"Duplicati is already running\" buttons {\"Stop installation\", \"Continue\"} default button 1" \ + -e "if button returned of question is equal to \"Stop installation\" then return \"STOP\""` + if [ "$RES" == "STOP" ]; + then + exit 1 + fi +fi \ No newline at end of file diff --git a/Installer/OSX/daemon-scripts/postinstall b/Installer/OSX/daemon-scripts/postinstall new file mode 100755 index 000000000..96e19e2e2 --- /dev/null +++ b/Installer/OSX/daemon-scripts/postinstall @@ -0,0 +1,4 @@ +#!/bin/sh + +set -e +/bin/launchctl load "/Library/LaunchDaemons/com.duplicati.app.launchagent.plist" \ No newline at end of file diff --git a/Installer/OSX/daemon-scripts/preinstall b/Installer/OSX/daemon-scripts/preinstall new file mode 100755 index 000000000..ba2e85c43 --- /dev/null +++ b/Installer/OSX/daemon-scripts/preinstall @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e +if /bin/launchctl list "com.duplicati.app.launchagent" &> /dev/null; then + /bin/launchctl unload "/Library/LaunchDaemons/com.duplicati.app.launchagent.plist" +fi \ No newline at end of file diff --git a/Installer/OSX/daemon/com.duplicati.app.launchagent.plist b/Installer/OSX/daemon/com.duplicati.app.launchagent.plist new file mode 100644 index 000000000..bd3290fb1 --- /dev/null +++ b/Installer/OSX/daemon/com.duplicati.app.launchagent.plist @@ -0,0 +1,15 @@ + + + + + Label + com.duplicati.app + ProgramArguments + + /usr/bin/open + /Applications/Duplicati.app + + RunAtLoad + + + diff --git a/Installer/OSX/make-dmg.sh b/Installer/OSX/make-dmg.sh index 922d6429a..2ea1e0377 100644 --- a/Installer/OSX/make-dmg.sh +++ b/Installer/OSX/make-dmg.sh @@ -7,7 +7,6 @@ WC_DMG=wc.dmg WC_DIR=wc TEMPLATE_DMG=template.dmg -SOURCE_FILES=Duplicati.app OUTPUT=Duplicati.dmg UNWANTED_FILES="AlphaVSS.Common.dll AlphaFS.dll AlphaFS.dll.config AlphaVSS.Common.dll.config appindicator-sharp.dll SQLite win-tools alphavss control_dir Duplicati.sqlite run-script-example.bat lvm-scripts Duplicati.debug.log SVGIcons" @@ -34,7 +33,14 @@ then exit fi -OUTPUT="Duplicati.dmg" +if [ ! -f "$1" ] +then + echo "Please supply a packaged zip file as the first input argument" + exit +fi + +VERSION_NUMBER=`echo "$1" | awk -F- '{print $2}' | awk -F_ '{print $1}'` + VERSION_NAME="Duplicati" if [ -e "$OUTPUT" ] then @@ -44,51 +50,93 @@ fi # Remove any existing work copy if [ -e "Duplicati.app" ] then - rm -rf "Duplicati.app" + sudo rm -rf "Duplicati.app" fi -# Get the current binary distribution -echo "Not building, using existing build ..." -#xbuild /property:Configuration=Release /target:Clean ../../Duplicati.sln -#xbuild /property:Configuration=Release ../../Duplicati.sln +# Create folder structure +mkdir "Duplicati.app" +mkdir "Duplicati.app/Contents" +mkdir "Duplicati.app/Contents/MacOS" +mkdir "Duplicati.app/Contents/Resources" -if [ ! -e ../../Duplicati/GUI/Duplicati.GUI.MacTrayIcon/bin/Release/Duplicati.GUI.MacTrayIcon.app ]; then - echo "Please build the Duplicati.GUI.MacTrayIcon project in Release mode with Xamarin Studio" - exit -fi +# Extract the zip into the Resouces folder +unzip -q "$1" -d "Duplicati.app/Contents/Resources" -mv ../../Duplicati/GUI/Duplicati.GUI.MacTrayIcon/bin/Release/Duplicati.GUI.MacTrayIcon.app Duplicati.app -cp -R ../../Duplicati/Server/webroot Duplicati.app/Contents/MonoBundle/ +# Install the Info.plist and icon +SHORT_VERSION_NUMBER=`echo ${VERSION_NUMBER} | awk -F. '{printf $1; printf "."; printf $2; printf "."; print $3}'` +PLIST=`cat "Info.plist"` +PLIST=${PLIST/!LONG_VERSION!/${VERSION_NUMBER}} +PLIST=${PLIST/!SHORT_VERSION!/${SHORT_VERSION_NUMBER}} +echo ${PLIST} > "Duplicati.app/Contents/Info.plist" +cp "Duplicati.icns" "Duplicati.app/Contents/Resources" if [ -e ./oem.js ]; then echo "Installing OEM script" - cp ./oem.js Duplicati.app/Contents/MonoBundle/webroot/scripts/ + cp ./oem.js Duplicati.app/Contents/Resources/webroot/scripts/ fi if [ -e ../oem.js ]; then echo "Installing OEM script" - cp ../oem.js Duplicati.app/Contents/MonoBundle/webroot/scripts/ + cp ../oem.js Duplicati.app/Contents/Resources/webroot/scripts/ fi if [ -e ./oem.css ]; then echo "Installing OEM stylesheet" - cp ./oem.css Duplicati.app/Contents/MonoBundle/webroot/stylesheets/ + cp ./oem.css Duplicati.app/Contents/Resources/webroot/stylesheets/ fi if [ -e ../oem.css ]; then echo "Installing OEM stylesheet" - cp ../oem.css Duplicati.app/Contents/MonoBundle/webroot/stylesheets/ + cp ../oem.css Duplicati.app/Contents/Resources/webroot/stylesheets/ fi +# Install executables +cp "run-with-mono.sh" "Duplicati.app/Contents/MacOS/" +cp "Duplicati-trayicon-launcher" "Duplicati.app/Contents/MacOS/duplicati" +cp "Duplicati-commandline-launcher" "Duplicati.app/Contents/MacOS/duplicati-cli" +cp "Duplicati-server-launcher" "Duplicati.app/Contents/MacOS/duplicati-server" +chmod +x "Duplicati.app/Contents/MacOS/run-with-mono.sh" +chmod +x "Duplicati.app/Contents/MacOS/duplicati" +chmod +x "Duplicati.app/Contents/MacOS/duplicati-cli" +chmod +x "Duplicati.app/Contents/MacOS/duplicati-server" + # Remove some of the files that we do not like for FILE in $UNWANTED_FILES do - if [ -e "Duplicati.app/$FILE" ] + if [ -e "Duplicati.app/Contents/Resources/${FILE}" ] then - rm -rf "Duplicati.app/$FILE" + rm -rf "Duplicati.app/Contents/Resources/${FILE}" fi done +# Set permissions +sudo chown -R root:admin "Duplicati.app" +sudo chown -R root:wheel "daemon/com.duplicati.app.launchagent.plist" +sudo chmod -R 644 "daemon/com.duplicati.app.launchagent.plist" +sudo chmod +x daemon-scripts/postinstall +sudo chmod +x daemon-scripts/preinstall +sudo chmod +x app-scripts/postinstall +sudo chmod +x app-scripts/preinstall + +# Make a PKG file, commented out lines can be uncommented to re-generate the lists +#pkgbuild --analyze --root "./Duplicati.app" --install-location /Applications/Duplicati.app "InstallerComponent.plist" +pkgbuild --scripts app-scripts --identifier com.duplicati.app --root "./Duplicati.app" --install-location /Applications/Duplicati.app --component-plist "InstallerComponent.plist" "DuplicatiApp.pkg" +pkgbuild --scripts daemon-scripts --identifier com.duplicati.app.daemon --root "./daemon" --install-location /Library/LaunchAgents "DuplicatiDaemon.pkg" +#productbuild --synthesize --package "DuplicatiApp.pkg" "Distribution.xml" +productbuild --distribution "Distribution.xml" --package-path "." "Duplicati.pkg" + +# Alternate to allow fixing the package +#productbuild --distribution "Distribution.xml" --package-path . "DuplicatiTmp.pkg" +#pkgutil --expand "DuplicatiTmp.pkg" "DuplicatiIntermediate" +#pkgutil --flatten "DuplicatiIntermediate" "Duplicati.pkg" +#rm -rf "DuplicatiTmp.pkg" + +rm -rf "DuplicatiApp.pkg" +rm -rf "DuplicatiDaemon.pkg" + +# For later, sign the package as well: +#productsign --sign "Developer ID Installer: John Doe" "Duplicati.pkg" "Duplicati-signed.pkg" + # Prepare a new dmg echo "Building dmg" if [ "$DELETE_DMG" -eq "1" ] @@ -100,7 +148,6 @@ else cp "$TEMPLATE_DMG" "$WC_DMG" fi - # Make a mount point and mount the new dmg mkdir -p "$WC_DIR" hdiutil attach "$WC_DMG" -noautoopen -quiet -mountpoint "$WC_DIR" @@ -115,12 +162,8 @@ then rm -rf "$WC_DIR/Duplicati.app" fi -mv "Duplicati.app" "$WC_DIR/Duplicati.app" -cp "Duplicati-commandline-launcher" "$WC_DIR/Duplicati.app/Contents/MacOS/duplicati-cli" -cp "Duplicati-server-launcher" "$WC_DIR/Duplicati.app/Contents/MacOS/duplicati-server" -chmod +x "$WC_DIR/Duplicati.app/Contents/MacOS/duplicati-cli" -chmod +x "$WC_DIR/Duplicati.app/Contents/MacOS/duplicati-server" - +# Move in the prepared folder +sudo mv "Duplicati.app" "$WC_DIR/Duplicati.app" # Unmount the dmg hdiutil detach "$WC_DIR" -quiet -force diff --git a/Installer/OSX/run-with-mono.sh b/Installer/OSX/run-with-mono.sh new file mode 100644 index 000000000..868fccac3 --- /dev/null +++ b/Installer/OSX/run-with-mono.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# +# This is a stub script that allows .apps to be relocatable on OSX but still +# find the managed assembly. +# +# This is copied from the Mono macpack tool and modified to fit Duplicati +# +# The Mono Version Check is from here: +# http://mjhutchinson.com/journal/2010/01/24/creating_mac_app_bundle_for_gtk_app +# + +# Figure out the full path to this script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +if [ "z${SCRIPT_DIR}" == "z" ]; then + SCRIPT_DIR="$( dirname "$0" )" +fi + +APP_PATH="$( dirname "${SCRIPT_DIR}" )" + +export GDIPLUS_NOX=1 + +#mono version check + +REQUIRED_MAJOR=2 +REQUIRED_MINOR=8 + +VERSION_TITLE="Cannot launch $APP_NAME" +VERSION_MSG="$APP_NAME requires the Mono Framework version $REQUIRED_MAJOR.$REQUIRED_MINOR or later." +DOWNLOAD_URL="http://www.go-mono.com/mono-downloads/download.html" + +# Try system default mono if an override was not supplied +if [ "z${MONO_BIN}" == "z" ]; then + MONO_BIN=`which mono` + + # Check if there was no mono found + if [ "z$MONO_BIN" == "z" ] + then + # Check if there is a HomeBrew install of mono instead + MONO_VERSION="$(/usr/local/bin/mono --version | grep 'Mono JIT compiler version ' | cut -f5 -d\ )" + if [ -f "/usr/local/bin/mono" ] + then + MONO_BIN="/usr/local/bin/mono" + fi + fi +fi + +MONO_VERSION="$(${MONO_BIN} --version | grep 'Mono JIT compiler version ' | cut -f5 -d\ )" +MONO_VERSION_MAJOR="$(echo $MONO_VERSION | cut -f1 -d.)" +MONO_VERSION_MINOR="$(echo $MONO_VERSION | cut -f2 -d.)" +if [ -z "$MONO_VERSION" ] \ + || [ $MONO_VERSION_MAJOR -lt $REQUIRED_MAJOR ] \ + || [ $MONO_VERSION_MAJOR -eq $REQUIRED_MAJOR -a $MONO_VERSION_MINOR -lt $REQUIRED_MINOR ] +then + osascript \ + -e "set question to display dialog \"$VERSION_MSG\" with title \"$VERSION_TITLE\" buttons {\"Cancel\", \"Download...\"} default button 2" \ + -e "if button returned of question is equal to \"Download...\" then open location \"$DOWNLOAD_URL\"" + echo "$VERSION_TITLE" + echo "$VERSION_MSG" + exit 1 +fi + +# Move into the folder where all the assemblies are located +cd "${APP_PATH}/Resources" + +# Make a symlink so Duplicati shows up as "Duplicati" in ps and not as "mono" +if [ ! -d "./bin" ]; then mkdir bin ; fi + +if [ ! -d "./bin" ] +then + # We cannot make the extra dir (most likely we are running on read-only medium) + # Instead we attempt to use exec to set the appname + OSX_VERSION=$(uname -r | cut -f1 -d.) + if [ $OSX_VERSION -lt 9 ]; then # If OSX version is 10.4 + exec "${MONO_BIN}" "$ASSEMBLY" $@ + else + exec -a "$APP_NAME" "${MONO_BIN}" "$ASSEMBLY" $@ + fi +else + + # We can make the helper file, lets use that + if [ -f "./bin/$APP_NAME" ]; then rm -f "./bin/$APP_NAME" ; fi + ln -s "${MONO_BIN}" "./bin/$APP_NAME" + + # Start Duplicati using the renamed symlink to Mono + "./bin/$APP_NAME" "$ASSEMBLY" $@ +fi \ No newline at end of file