Da Ploy, Book II
In a previous episode, i outlined how i build MercuryMover (The best program to move and resize windows on your Mac via your keyboard) and deploy new builds to my website. One item that i knew would be controversial among other Mac developers was the use of an Installer package as the medium through which i distributed MercuryMover. In general an installer is not The Mac Way. I knew this, but didn't think that i could provide a good experience for my users without it. Many of the good people on the Macintosh Software Business (MacSB) list challenged me to try again. What really made me decide to rethink the installer were some colleagues from MacSB who are shipping products that have installation requirements that are similar to MercuryMover. The folks from Atomic Bird, and Noodlesoft (the authors of MondoMouse and Hazel respectively) generously shared their experience with me. Both ship a plain ole' .prefPane file on a Disk Image. By using a Disk Image with a background, they are able to provide a very pleasant experience for their users, including providing the instructions on how to install the app. Most importantly for me, both Noodlesoft and Atomic Bird report that this strategy requires very little support for their users. Since i have no experience and they have a lot, I'm extremely grateful to have the benefit of theirs. Taking their advice, i made a small change to MercuryMover's PreferencePane so that when it opens, it compares MercuryMoverAgent's version to it's own and restarts it if they don't match (see the previous episode for details).
Having decided to go the Disk Image/Plain PrefPane route and made the necessary changes to MercuryMover, my previously finished build/deploy procedure was now just about coming to a middle. First i needed a disk image background, then i needed to figure out how to place a background on a disk image and get it to mount in icon mode (with my background and my prefpane positioned in the right place). Finally, i needed to be able to create the disk image via my build/deploy script so that i can still put out new builds with one command. As an added bonus, it would be nice to also show my EULA (End User License Agreement) when the Disk Image mounts.
Background Image
Whenever you open a disk image and it looks like a web page, really what you are looking at is a plain old Finder folder window, opened in icon mode with a pretty background image. I'm not much of a designer, so i kept mine pretty simple. I lifted the Helium Foot Software "logo" from my web site and placed the "MercuryMover" title inside a faux bezel reminiscent of the one in MercuryMover itself. There are some instructions at the bottom and big space in the middle for the MercuryMover.prefPane icon to go. I laid this all out with The Gimp. While I appreciate how powerful The Gimp is, and that it's open source, i struggled mightily to get my simple image to lay out how i imagined it. Next time, i'll definitely plunk down the money for an Acorn license.
Disk Image Layout
With the pretty stuff out of they way, it was time to get down to business. My main resource for how to actually create the disk image came from this page on Jamie Zawinski's blog. The trick is to create a "read-write" disk image using Disk Utility from a folder with the following stuff in it:
- your program
- your background image in a folder called .background (this folder can have any name, but prepending the dot will keep this folder from showing in the finder.)
That "read-write" part is critical, so make sure that you select "read-write" from the "Image Format" menu when you create the image. If you use the default value ("Compressed") then any changes that you make to the layout of the window will get lost when you unmount the disk, completely defeating the purpose of this exercise.
Now mount the disk image, and use the finder to set the window to icon mode (command-1) and show the view options palette (command-j). Use the view options palette to set your background image as the one on the disk image in the .background folder. Also, place your program icon wherever you want it in the window. Now for the critical step: unmount the disk image, remount it and make a copy of the .DS_Store file that resides at the root of your mounted image. By keeping a copy of this file, you'll be able to recreate the disk image without all of the mousing and clicking. The unmount/remount dance is necessary because the finder doesn't serialize the state of the dmg's finder window until it is unmounted.
Automate
It's all well and good to create a disk image by hand, but i ain't doing that each time i need to push up a new build. Especially since i'm likely to be in a hurry to fix whatever bug the trials by fire has uncovered. The jwz post tipped me off to an excellent script from the friendly Mozilla folks called pkg-dmg. As the name implies, pkg-dmg packages a dmg and oh so much more:
- copies in my background image
- includes my EULA and displays it when the Disk Image mounts (this step is surprisingly difficult to accomplish without the script)
- copies my .DS_Store file
Boom goes the dynamite:
#copy the built prefPane to my dmg "source" folder (the folder from which the image will be built)
cp -r ${PRODUCT_PATH} ${DMG_SOURCE_PATH}
#build the dmg and they will come?
./pkg-dmg --target ${DMG_PATH} --source ${DMG_SOURCE_PATH} --volname ${PRODUCT_NAME} --license ${PROJECT_DIR}/documents/EULA.txt --copy ${PROJECT_DIR}/dmg/DS_Store:/.DS_Store --mkdir /.background --copy ${PROJECT_DIR}/dmg/background.png:/.background
Two things to note:
- those --copy options are colon separated where the first item is the source file path relative to `pwd`, the second item is destination path relative to the root of the newly created Disk Image.
- I spent about two hours looking at error message spit out by /Developer/usr/bin/Rez (called by pkg-dmg). I was just about ready to give up when on a whim i tried normalizing the line endings (and setting them to LF) in my EULA.txt file . LF and behold, it worked!
I swear that this is the last change to my deployment strategy before the launch. While i'm extremely happy with the result, i'm not 100% sure that this was the best use of my time in the few weeks before the launch. I keep telling myself that the impression that the downloaded file and installer make is critical. If users download MercuryMover and don't try it out, then all of my effort will have been wasted (and rest assured that only a fraction of that effort has been chronicled here). Want to see how it turned out? Go ahead and try the beta.
13 days until launch.