Installing on my Mac at home

I’m in the office and I want to start installing some software on my laptop at home so it’s ready to try when I get back to my laptop. (The test suite is running and I know the install will take a while, so it can get going while I commute!) In particular, I was looking to try Vagrant, which requires VirtualBox.

First step: Back to my Mac. Turns out, if you’re sensible enough to have SSH running on your Mac (enable it under Sharing in System Preferences), it’s available from other Macs where you have your MobileMe account set up. Simply run:

ssh <hostname>.<MobileMe name>.members.mac.com

where <hostname> is the short name of your laptop and <MobileMe name> is your MobileMe login. So, for example:

ssh jura.mathie.members.mac.com

gets me to my laptop. (Interestingly, this doesn’t resolve on hosts where you’re not logged in to your MobileMe account, so there’s some DNS resolution magic going on locally. At least I hope so, and I’ve not just exposed myself on the Internet!)

Next up, let’s grab VirtualBox. Head across to the web site to figure out the latest download URL, and download it with curl:

curl -LO http://[...]/VirtualBox-4.0.2-69518-OSX.dmg

Once it’s downloaded, we have to mount the disk image. The simplest way with Mac OS X is to use hdiutil:

hdiutil attach VirtualBox-4.0.2-69518-OSX.dmg

This will mount the disk image on /Volumes/VirtualBox. Now we have to run the installer, which we can do headless:

sudo installer -pkg /Volumes/VirtualBox/VirtualBox.mpkg -target / -verbose

This needs to run as root, hence sudo. Since it’s verbose, it’ll spit out a bunch of progress stuff, because we asked it to be verbose. But that’s it. Thanks to having a standard installer, we can install Mac OS X packages without a GUI. Win.

We should tidy up after ourselves by unmounting the disk image:

hdiutil detach /Volumes/VirtualBox

And we’re done. VirtualBox is installed, and I can get onto the long running download of grabbing the demo Ubuntu 10.04 LTS image for Vagrant (which clocks in at nearly 500MB). Getting started with Vagrant is another story entirely, which I’m sure I’ll talk about sometime soon.

Well, we’re nearly done. Let’s finish up by freaking out whoever’s in the house:

say "We're watching you!"

:-)

Objective-C message passing semantics for Ruby

While I was writing a bit of code today (which smells a bit and so I suspect needs revisiting in the future, but anyway) I found myself writing the equivalent of:

object.respond_to?(method) ? object.send(method, args) : nil

that is, if a particular object implements a method then please call it and let me know what it returns, otherwise just pretend I never asked and return nil. While mulling over the git diff, it occurred to me that is (if I remember correctly) exactly how Objective-C behaves by default with message passing.

And so could Ruby:

Kernel.module_eval do
  def method_missing(*args, &block)
    nil
  end
end

I am in no way advocating this as not being insane (a number of projects rely on the existing default method_missing implementation which raises an exception), but it is possible. :-)

Let’s see it in action in irb. Before:

irb(main):001:0> o = Object.new
=> #<object:0x30b164>
irb(main):002:0> o.method_that_does_not_exist
NoMethodError: undefined method `method_that_does_not_exist' for #<object:0x30b164>
    from /Users/mathie/.irbrc:210:in `method_missing'
    from (irb):2

And after:

irb(main):008:0> o = Object.new
=> #<object:0x4fbb4>
irb(main):009:0> o.method_that_does_not_exist
=> nil

Could be useful if Objective-C is your hammer and you find yourself trying to use Ruby as a hammer instead?

Read-only clones and commiting changes to submodules

Hopefully this will be a shorter article, but I thought I’d get the tip into Google before I forget it and have to Google for the answer. :-)

Imagine the situation. You’re using Git submodules to manage your external dependencies, for example Rails plugins. Since not everybody on the project has push access to some of the plugins, naturally you’re using the public clone URL as the submodule URL for your project:

mathie@tullibardine:books$ git submodule add git://github.com/rubaidh/timestamped_booleans vendor/plugins/timestamped_booleans
Initialized empty Git repository in /Users/mathie/tmp/src/books/vendor/plugins/timestamped_booleans/.git/
[ ... ]

While some of the rest of your team don’t have push access to that particular repository, you do. While you’re working away, you happen to make a change to the submodule and commit it locally. Being a good submodule user, you know you must push those changes before you push the main repository, otherwise your coworkers will be stuck with a repository that references a tree that doesn’t yet exist in a repository they have access to. This is git speak for “the end of the world”.

So, how do we push those changes out when we’ve pulled from the read-only view of the repository? Well, we add another remote:

mathie@tullibardine:books$ cd vendor/plugins/timestamped_booleans/
mathie@tullibardine:timestamped_booleans$ git remote add writable git@github.com:rubaidh/timestamped_booleans.git
mathie@tullibardine:timestamped_booleans$ git push writable master
[ ... ]

Sorted. The changes are now committed for that submodule and we can happily push our other changes to the main repository too.