Dr Nic

Packaging TextMate bundles in OS X DMGs

Last week Engine Yard released a CLI for their Engine Yard AppCloud. Delights such as:

ey deploy
ey rebuild
ey logs
ey ssh

Engine Yard.tmbundle

They simultaneously released a TextMate bundle to deploy, rebuild, view logs, etc using Ctrl+Alt+Cmd+E. Like all TextMate bundles, you can install it in one of two ways: via git (see the README), or via a beautiful DMG. Download it here!

Yes indeed, TextMate bundles can now be packaged up and distributed via DMGs using ChocTop!

Ruby on Rails.tmbundle

For example, the Ruby on Rails.tmbundle using a simple purple theme.

First, the Engine Yard tmbundle

To use the Engine Yard tmbundle, you first need to install and use the CLI once. Instructions at the bottom of the information page.

How to package a TextMate bundle into a DMG

ChocTop is a packaging and distribution tool originally designed only for Cocoa applications, but can now package any assets, URL links, or even the whole project folder itself. This makes it ideal for packaging TextMate bundles which have no compiled/built output to distribute (like a Cocoa application), rather the project folder itself is the distributed item (the Engine Yard.tmbundle folder in this case).

Getting started

Everything is added into your TextMate bundle project. For example, with the EngineYard bundle:

gem install choctop
cd Library/Application\ Support/TextMate/Bundles/Engine\ Yard.tmbundle
install_choctop . --tmbundle

If your tmbundle already has a Rakefile, then don’t overwrite it. Instead, inside the Rakefile, add the ChocTop configuration:

require "choctop"

ChocTop::Configuration.new do |s|
  s.add_root :position => [290, 200], :exclude => %w[appcast build .bundle .git]
  s.add_link 'http://github.com/engineyard/engineyard.tmbundle', 'GitHub', :position => [520, 200]
  s.defaults :textmate
end

For TextMate bundles the DMG magic is from the s.add_root line. The resulting DMG will include the entire project as a folder/bundle. For example, you’ll want to exclude appcast, build, .bundle (if you’re using Bundler), and .git folders.

The s.defaults :textmate provides a generic background and volume icon for a TextMate bundle DMG. See below for customising the background and volume icons. The :position coordinates above are for the generic background.

Building your DMG

To build your DMG and then view it in Finder:

rake dmg
open appcast/build/*.dmg
# or together
rake dmg[automount]

You can now share the DMG file. See below for how to upload it to a server.

Versioning

In future, it would be great to use Sparkle’s auto-update mechanism (as seen in nearly every Cocoa application). ChocTop will automatically generate the required XML feed; TextMate nor the bundle has a way to ask Sparkle to poll for it nor update itself, yet.

But, you can start versioning your DMGs today:

$ rake version:current
0.0.0
$ rake version:bump:major
$ rake version:current
1.0.0
$ rake dmg

The DMG will now have a version number.

Uploading new DMG versions

The original ChocTop was designed for Cocoa applications and included Sparkle support so your Cocoa applications automatically updated themselves when you built and uploaded a new version. I haven’t got a solution for this for TextMate bundles yet; but it seems like a good idea for the future.

Nonetheless, ChocTop still includes a rake upload task to ship new versions of your DMG to a server somewhere.

In your Rakefile, add the following config lines to the ChocTop block:

s.base_url   = 'http://some.host.com/upload/folder'
s.remote_dir = '/path/to/upload/folder'
s.host       = 'some.host.com'
s.user       = 'remote-user'

The s.base_url is the URL from where the DMG file will be found by users. Later, when I figure out how to do auto-updating of the TextMate bundles, it will also use this URL. This URL is also used to determine the host for uploading the file.

The s.remote_dir is a path on the target server that maps to the base_url. This folder must already exist; rsync cannot create it as far as I can tell. So ssh into the machine and mkdir -p /path/to/upload/folder

The latter two are optional: s.host is derived from s.base_url and s.user defaults to your current local user.

To upload the latest DMG, run:

rake upload

You can now share the URL http://some.host.com/upload/folder for people to download the DMG. A small PHP script redirects from the folder path to the DMG filename.

Customising

ChocTop allows you to customise nearly everything.

The s.defaults :textmate line is similar to the following configuration:

s.background_file = "...choctop/assets/textmate_background.jpg"
s.volume_icon     = "...choctop/assets/textmate_volume.icns"
s.icon_size       = 104
s.icon_text_size  = 12

For TextMate bundles, perhaps put customised assets into a Support/dmg folder.

A background image should include blank space for the large YourBundle.tmbundle icon and webloc URL file to your GitHub project (or other target URLs). There are no size constraints on the background image. Design something beautiful.

The volume icon is an icns file. You create this using OS X’s Icon Composer application. Start with a transparent png file and drop it into the box with the corresponding size.

For the Engine Yard tmbundle, the following configuration is used:

s.background_file = 'Support/dmg/engineyard.tmbundle.dmg.png'
s.volume_icon     = 'Support/dmg/engineyard.dmg.icns'

Additional files

If there are other files you explicitly want bundled in the DMG, say a pretty README.html or a folder of documentation, then you can specify them:

s.add_file 'README.html', :position => [50, 100]
s.add_file 'docs', :position => [100, 100], :name => 'Documentation'

Summary

ChocTop is pretty cool for bundling any set of files into a custom DMG, especially Cocoa applications and now TextMate bundles.

Hopefully one day we can have Sparkle auto-updates for TextMate bundles too.

Related posts:

  1. Instant new Rails applications with the App Scrolls When I start a new project I want to start...
  2. Trialing RedCar instead of TextMate – replacing my aliases I’m interested to trial RedCar in my life, instead of...
  3. Validate and Save your Ruby in TextMate – with secret Rubinus superpowers In some TextMate bundles, if you save a file it...
  4. TextMate easter egg: find bundle commands by key combo I’ve dreamed of the ability to ask TextMate “what frigging...
  5. Using Ruby within TextMate snippets and commands I didn’t know you could run Ruby within TextMate snippets....

One Response to “Packaging TextMate bundles in OS X DMGs”

  1. [...] This post was mentioned on Twitter by Dr Nic, Oliver Barnes. Oliver Barnes said: RT @drnic: How to package any textmate bundle into a pretty DMG http://drnicwilliams.com/2010/08/01/packaging-textmate-bundles-in-os-x-dmgs/ [...]