Pharo: How to load a Metacello Configuration into an offline image

I just had a little, maybe weird sounding problem.

I needed to get Seaside and some other stuff into a Pharo image on a machine at a place where there is very limited offline access. The network there is configured in a way that not every application can download stuff from the web. Pharo, of course, is not on that list.

So the usual code snippet:

Gofer new
                  squeaksource: 'MetacelloRepository';
                  package: 'ConfigurationOfSeaside30';

         ((Smalltalk at: #ConfigurationOfSeaside30) project latestVersion) load.

simply doesn’t work.
So my idea was to use the web browser to download all the monticello packages by hand (which is possible at the place) using the web browser and copying all of them into a directory.

I started off by downloading the ConfigurationOfSeaside30 package from and loading it into the image using monticello. From there one, I could probably find out which packages I need.

Well, good idea, but how do I actually find out which ones I need?Of course, all that’s required to load is described in the Configuration Class, but being a Metacello config, it would pre-load other configs that describe even more packages to load.
So without having Pharo accessing the web, there’s no way of determining which packages to load. The snippet

ConfigurationOfSeaside30 project latestVersion fetch loadDirective

would give me all the information I need …. if #fetch would really work. But I am offline.Oh my…

My next idea was to use a machine that’s on another network and where Pharo can access Squeaksource and load the config there. I used a clean image with an empty package-cache subdirectory, so that I simply had to zip all the mcz files in there and could copy them to the target machine.

So I created a directory on the target machine and copied all the packages into it.

Then I needed a way to convince Metacello/Gofer to use this local directory instead of Squeaksource.

Fortunately, Norbert and Dale answered my question on the Metacello Group at Google and pointed me to the perfect place to find what I needed: the Metacello FAQ, specifically the question “How do I override the repository for a config?”.

So, for completness’ sake, here’s how I got to load the whole config from a local directory:

| version repo |
  repo := MCDirectoryRepository new.
  repo directory: (FileDirectory on: '<path to directory>').
  version := ConfigurationOfSeaside30 project latestVersion.
  version repositoryOverrides: (OrderedCollection with: repo).
  version load.

It’s easy once you’ve got all the Configurations and Packages at hand. But still there is a problem of how to find out which ones you need. I just circumvented the problem, but maybe there is a better way of reaching the goal. Maybe it would be a good idea to have some sort of web service that bundles all the packages into a big zip file that one can download without using a Smalltalk image – for whatever reason.

In fact, putting up a Pharo or Squeak Image as a seaside Server that simply does the #loadDirective thing and packs all the files into a zip and delivers it to the user, would be all it needs to do. That’s maybe a nice exercise to dip my feet a bit deeper into Pharo…

This post is mostly a memo to myself to look this stuff up later when I need it again, but maybe it’s helpful for others as well.

[Update] Just a few minutes after I had finished this post another thought crept into my head:

I wonder if the idea of having such an extraction tool isn’t helpful for more scenarios than the one I’ve mentioned here. In most companies you have to hand the complete source code of a specific product version into a special version control system before it goes into production. This repos is independent of the development VCS and only keeps deliverables.

So an extract of a repo that includes a complete ConfigurationOfXXX with all required packages in their specific versions is exactly what’s needed for this. [/Update]