From 20680d93f0b6f9fdfe835863891f201f2aaaf4ab Mon Sep 17 00:00:00 2001 From: Pavel Date: Sat, 27 Sep 2014 15:16:58 +0700 Subject: [PATCH] Add build dog task --- README.md | 2 +- Rakefile | 15 ++ build_files/yoursway-create-dmg/.gitignore | 1 + build_files/yoursway-create-dmg/LICENSE | 21 ++ build_files/yoursway-create-dmg/README.md | 55 +++++ .../builder/create-dmg.builder | 26 +++ build_files/yoursway-create-dmg/create-dmg | 221 ++++++++++++++++++ build_files/yoursway-create-dmg/sample | 3 + .../support/dmg-license.py | 141 +++++++++++ .../support/template.applescript | 77 ++++++ 10 files changed, 561 insertions(+), 1 deletion(-) create mode 100755 build_files/yoursway-create-dmg/.gitignore create mode 100755 build_files/yoursway-create-dmg/LICENSE create mode 100755 build_files/yoursway-create-dmg/README.md create mode 100755 build_files/yoursway-create-dmg/builder/create-dmg.builder create mode 100755 build_files/yoursway-create-dmg/create-dmg create mode 100755 build_files/yoursway-create-dmg/sample create mode 100755 build_files/yoursway-create-dmg/support/dmg-license.py create mode 100755 build_files/yoursway-create-dmg/support/template.applescript diff --git a/README.md b/README.md index ef06151c..3f58aa68 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ To run newest version, simply: To make a release, run: - ./build + rake build New release will be at: `~/Postbird.app` diff --git a/Rakefile b/Rakefile index dba0b865..2b401f68 100644 --- a/Rakefile +++ b/Rakefile @@ -1,3 +1,18 @@ task :build do exec "./build_files/build.sh" +end + +task :build_dmg do + file_name = "Postbird-0.3.dmg" + File.delete("~/#{file_name}") if File.exist?("~/#{file_name}") + + exec %{ + ./build_files/yoursway-create-dmg/create-dmg \ + --volname "Postbird 0.3" \ + --volicon "./build_files/icon.icns" \ + --icon Postbird.app 50 50 \ + --app-drop-link 300 50 \ + ~/#{file_name} \ + ~/Postbird.app + } end \ No newline at end of file diff --git a/build_files/yoursway-create-dmg/.gitignore b/build_files/yoursway-create-dmg/.gitignore new file mode 100755 index 00000000..90ec22be --- /dev/null +++ b/build_files/yoursway-create-dmg/.gitignore @@ -0,0 +1 @@ +.svn diff --git a/build_files/yoursway-create-dmg/LICENSE b/build_files/yoursway-create-dmg/LICENSE new file mode 100755 index 00000000..349b6d82 --- /dev/null +++ b/build_files/yoursway-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/build_files/yoursway-create-dmg/README.md b/build_files/yoursway-create-dmg/README.md new file mode 100755 index 00000000..075cf07f --- /dev/null +++ b/build_files/yoursway-create-dmg/README.md @@ -0,0 +1,55 @@ +yoursway-create-dmg +=================== + +A shell script to build fancy DMGs. + + +**INSTALLATION** + +By being a shell script, yoursway-create-dmg installation is very simple. Simply download and run. + +> git clone https://github.com/andreyvit/yoursway-create-dmg.git +> cd yoursway-create-dmg +> ./create-dmg [options] + + +**USAGE** + +> create-dmg [options...] [output\_name.dmg] [source\_folder] + +All contents of source\_folder will be copied into the disk image. + +**Options:** + +* **--volname [name]:** set volume name (displayed in the Finder sidebar and window title) +* **--volicon [icon.icns]:** set volume icon +* **--background [pic.png]:** set folder background image (provide png, gif, jpg) +* **--window-pos [x y]:** set position the folder window +* **--window-size [width height]:** set size of the folder window +* **--icon-size [icon size]:** set window icons size (up to 128) +* **--icon [file name] [x y]:** set position of the file's icon +* **--hide-extension [file name]:** hide the extension of file +* **--custom-icon [file name]/[custom icon]/[sample file] [x y]:** set position and custom icon +* **--app-drop-link [x y]:** make a drop link to Applications, at location x, y +* **--eula [eula file]:** attach a license file to the dmg +* **--no-internet-enable:** disable automatic mount© +* **--version:** show tool version number +* **-h, --help:** display the help + + +**EXAMPLE** + +> \#!/bin/sh +> test -f Application-Installer.dmg && rm Application-Installer.dmg +> create-dmg \ +> --volname "Application Installer" \ +> --volicon "application\_icon.icns" \ +> --background "installer\_background.png" \ +> --window-pos 200 120 \ +> --window-size 800 400 \ +> --icon-size 100 \ +> --icon Application.app 200 190 \ +> --hide-extension Application.app \ +> --app-drop-link 600 185 \ +> Application-Installer.dmg \ +> source\_folder/ diff --git a/build_files/yoursway-create-dmg/builder/create-dmg.builder b/build_files/yoursway-create-dmg/builder/create-dmg.builder new file mode 100755 index 00000000..d4285280 --- /dev/null +++ b/build_files/yoursway-create-dmg/builder/create-dmg.builder @@ -0,0 +1,26 @@ +SET app_name create-dmg + +VERSION create-dmg.cur create-dmg heads/master + +NEWDIR build.dir temp %-build - + +NEWFILE create-dmg.zip featured %.zip % + + +COPYTO [build.dir] + INTO create-dmg [create-dmg.cur]/create-dmg + INTO sample [create-dmg.cur]/sample + INTO support [create-dmg.cur]/support + +SUBSTVARS [build.dir]/create-dmg [[]] + + +ZIP [create-dmg.zip] + INTO [build-files-prefix] [build.dir] + + +PUT megabox-builds create-dmg.zip +PUT megabox-builds build.log + +PUT s3-builds create-dmg.zip +PUT s3-builds build.log diff --git a/build_files/yoursway-create-dmg/create-dmg b/build_files/yoursway-create-dmg/create-dmg new file mode 100755 index 00000000..b581913f --- /dev/null +++ b/build_files/yoursway-create-dmg/create-dmg @@ -0,0 +1,221 @@ +#! /bin/bash + +# Create a read-only disk image of the contents of a folder + +set -e; + +function pure_version() { + echo '1.0.0.2' +} + +function version() { + echo "create-dmg $(pure_version)" +} + +function usage() { + version + echo "Creates a fancy DMG file." + echo "Usage: $(basename $0) options... image.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)" + 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 " --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 " --eula eula_file" + echo " attach a license file to the dmg" + echo " --no-internet-enable" + echo " disable automatic mount©" + 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 + +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\"" + shift; shift;; + --icon-size) + ICON_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;; + --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;; + -*) + echo "Unknown option $1. Run with --help for help." + exit 1;; + esac +done + +test -z "$2" && { + echo "Not enough arguments. Invoke with --help for help." + exit 1 +} + +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)" + +AUX_PATH="$(dirname $0)/support" + +test -d "$AUX_PATH" || { + echo "Cannot find support directory: $AUX_PATH" + exit 1 +} + +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}" +ACTUAL_SIZE=`du -sm "$SRC_FOLDER" | sed -e 's/ .*//g'` +DISK_IMAGE_SIZE=$(expr $ACTUAL_SIZE + 20) +hdiutil create -srcfolder "$SRC_FOLDER" -volname "${VOLUME_NAME}" -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW -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 '^/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 '^/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 "$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 + +# run applescript +APPLESCRIPT=$(mktemp -t createdmg) +cat "$AUX_PATH/template.applescript" | 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/ICON_SIZE/$ICON_SIZE/g" | perl -pe "s/POSITION_CLAUSE/$POSITION_CLAUSE/g" | perl -pe "s/APPLICATION_CLAUSE/$APPLICATION_CLAUSE/g" | perl -pe "s/HIDING_CLAUSE/$HIDING_CLAUSE/" >"$APPLESCRIPT" + +echo "Running Applescript: /usr/bin/osascript \"${APPLESCRIPT}\" \"${VOLUME_NAME}\"" +"/usr/bin/osascript" "${APPLESCRIPT}" "${VOLUME_NAME}" || true +echo "Done running the applescript..." +sleep 4 + +rm "$APPLESCRIPT" + +# 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: +echo "Blessing started" +bless --folder "${MOUNT_DIR}" --openfolder "${MOUNT_DIR}" +echo "Blessing finished" + +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 "${DMG_TEMP_NAME}" -format UDZO -imagekey zlib-level=9 -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" + "${AUX_PATH}/dmg-license.py" "${DMG_DIR}/${DMG_NAME}" "${EULA_RSRC}" +fi + +if [ ! -z "${NOINTERNET}" -a "${NOINTERNET}" == 1 ]; then + echo "not setting 'internet-enable' on the dmg" +else + hdiutil internet-enable -yes "${DMG_DIR}/${DMG_NAME}" +fi + +echo "Disk image done" +exit 0 diff --git a/build_files/yoursway-create-dmg/sample b/build_files/yoursway-create-dmg/sample new file mode 100755 index 00000000..92697a98 --- /dev/null +++ b/build_files/yoursway-create-dmg/sample @@ -0,0 +1,3 @@ +#! /bin/bash +test -f test2.dmg && rm test2.dmg +./create-dmg --window-size 500 300 --background ~/Projects/eclipse-osx-repackager/build/background.gif --icon-size 96 --volname "Hyper Foo" --app-drop-link 380 205 --icon "Eclipse OS X Repackager" 110 205 test2.dmg /Users/andreyvit/Projects/eclipse-osx-repackager/temp/Eclipse\ OS\ X\ Repackager\ r10/ diff --git a/build_files/yoursway-create-dmg/support/dmg-license.py b/build_files/yoursway-create-dmg/support/dmg-license.py new file mode 100755 index 00000000..c2f6fbf9 --- /dev/null +++ b/build_files/yoursway-create-dmg/support/dmg-license.py @@ -0,0 +1,141 @@ +#! /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 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. +""" +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 'LPic' (5000) { + $"0002 0011 0003 0001 0000 0000 0002 0000" + $"0000 000E 0006 0001 0005 0007 0000 0007" + $"0008 0000 0047 0009 0000 0034 000A 0001" + $"0035 000B 0001 0020 000C 0000 0011 000D" + $"0000 005B 0004 0000 0033 000F 0001 000C" + $"0010 0000 000B 000E 0000" +};\n\n""") + with open(license, 'r') as l: + f.write('data \'TEXT\' (5002, "English") {\n') + for line in l: + if len(line) < 1000: + f.write(' "' + line.strip().replace('"', '\\"') + + '\\n"\n') + else: + for liner in line.split('.'): + f.write(' "' + + liner.strip().replace('"', '\\"') + + '. \\n"\n') + f.write('};\n\n') + f.write("""resource 'STR#' (5002, "English") { + { + "English", + "Agree", + "Disagree", + "Print", + "Save...", + "IMPORTANT - By clicking on the \\"Agree\\" button, you agree " + "to be bound by the terms of the License Agreement.", + "Software License Agreement", + "This text cannot be saved. This disk may be full or locked, or the " + "file may be locked.", + "Unable to print. Make sure you have selected a printer." + } +};""") + os.system('/usr/bin/hdiutil unflatten -quiet "%s"' % dmgFile) + os.system('%s "%s/"*.r %s -a -o "%s"' % + (options.rez, options.flat_carbon, tmpFile, dmgFile)) + + os.system('/usr/bin/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) + print "Successfully added 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 a plain ascii text . + + 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( + '--flat-carbon', + '-f', + action='store', + default='/Applications/Xcode.app/Contents/Developer/Platforms' + '/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk' + '/Developer/Headers/FlatCarbon', + help='The path to the FlatCarbon headers. 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 or not os.path.exists(options.rez) \ + or not os.path.exists(options.flat_carbon) + if cond: + parser.print_usage() + sys.exit(1) + main(options, args) diff --git a/build_files/yoursway-create-dmg/support/template.applescript b/build_files/yoursway-create-dmg/support/template.applescript new file mode 100755 index 00000000..52934b1e --- /dev/null +++ b/build_files/yoursway-create-dmg/support/template.applescript @@ -0,0 +1,77 @@ +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 + end tell + + set opts to the icon view options of container window + tell opts + set icon size to ICON_SIZE + set arrangement to not arranged + end tell + BACKGROUND_CLAUSE + + -- Positioning + POSITION_CLAUSE + + -- Hiding + HIDING_CLAUSE + + -- Application Link Clause + APPLICATION_CLAUSE + close + open + + update without registering applications + -- 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 + + update without registering applications + 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 + + update without registering applications + 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