[Updated: 6/5/2010] For the latest documentation and information about Metacello, see the Metacello project pages.
Metacello is a package management system for Monticello. A package management system is…
A package management system provides a consistent method of installing software…
Last April I finally became fed up with the lack of a decent package management system for Monticello and decided to write my own from scratch. I wanted a package management system for Monticello that was consistent with the important features of Monticello:
- Declarative modeling. A Metacello project has named versions consisting of lists of explicit Monticello package versions. Dependencies are explicitly expressed in terms of named versions of required projects. A required project is a reference to another Metacello project.
- Distributed repositories. Metacello project metadata is represented as instance methods in a class therefore the Metacello project metadata is stored in a Monticello package. As a result, it is easy for distributed groups of developers to collaborate on ad hoc projects.
- Optimistic development. With Monticello-based packages, concurrent updates to the project metadata can be easily managed. Parallel versions of the metadata can be merged just like parallel versions of the code base itself.
Additionally, the following three points are important considerations for Metacello:
- Cross platform operation. Metacello must run on all platforms that support Monticello: currently Squeak, Pharo and GLASS.
- Conditional Monticello package loading. For projects that are expected to run on multiple platforms, it is essential that platform-specific Monticello packages can be conditionally loaded. At the moment, conditional loading is specified based upon the following attributes:
- #common. Code that is common across all platforms.
- #squeakCommon. Code that is common to Squeak and Pharo.
- #squeak. Code that is specific to Squeak.
- #pharo. Code that is specific to Pharo.
- #gemstone. Code that is specific to GemStone.
It should be possible to inject project-specific attributes, so code that is dependent upon attributes not covered by the standard list can be conditionally loaded. For example, in GLASS, different Monticello package versions are loaded based on which version of GemStone/S is running (i.e., version 2.0 versus 3.0).
- Compatible with MC2. It must be possible to manage Metacello projects that are based on alternate Distributed Source Code Management systems like Monticello2.
- MIT license.
[Update: 10/14/2009] Note that with the release of version 1.0-beta.3 of Metacello, some of the following sections are no longer valid . Please read this post for up-to-date information. The outright invalid entries have been struck out.
In the following sections I hope to give a taste of what Metacello can do along with instructions on loading Metacello into Squeak or Pharo, so you can run through the Metacello tutorial:
The VersionSpec
[Update: 10/14/2009] the following section is not completely accurate for the newer versions of Metacello (1.0-beta versions). Please see this discussion for up-to-date information.
Click on the image below to get a full depiction of a version spec.
The metadata for a Metacello project version is kept in a versionSpec which has the following atributes:
- blessing. A version can be tagged with a blessing like #alpha, #beta, #release, #development (or any other tag that is deemed useful). The blessing is used as a version filter. For example the latest version of a Metacello project is currently defined as the latest version whose blessing is not #development.
- description. Useful information about the version.
- packages. A list of Monticello package versions (or project references via required projects) that make up the project.
- repositories. A list of Monticello repositories from which the packages can be loaded.
- groups. An alias for a collection of packages. See Bootstrapping Metacello for some examples of using groups.
- doits. A collection of blocks associated with a Monticello package that are evaluated before and/or after a package is loaded.
- project package. A definition of the Monticello package name and Monticello repository from which the latest project metadata is be loaded.
- required projects. A list of projects that the Metacello project depends upon. A required project spec includes such information as the version of the project, the name of the Metacello project class, the package and repository from which the project metadata is loaded (note the similarity to the project package specification). Heres’ an example of a required project specification:
Any one of the versionSpec attributes may be conditionally modified. Here’s an example package specification that adds a new Monticello package version for the package ‘Example-Core’ when the #testPlatform attribute is present:
In the #common version spec, the package version ‘Example-Core-anon.14’ is associated with the ‘Example-Core’ package . When the #testPlatform attribute is present, ‘Example-Core.testplatform-anon.15’ overrides ‘Example-Core-anon.14’ in the version spec.
Metacello Tools
[Update: 10/14/2009] Note some of the entries in this section are invalid for later versions of Metacello. Please read this new section for more up-to-date information.
I have developed a minimal set of menu items for working with Metacello.
I started out thinking that I would completely avoid the tools issues and instead rely on workspace scripts, the Class Browser and Monticello Browser for the bulk of the tools support. Over time, I found a handful of operations that deserved to be easier to use, so I whipped up a handful of OB commands and attached them to the MetacelloProject class.
Select a MetacelloProject class and bring up the Class menu:
Save Packages
Finds the dirty Monticello packages that are members of the selected version of the Metacello project and saves them, prompting you for version name and commit comment. After the packages are saved you are prompted to Update Package Methods.
Update Package Methods
Automatically updates the package spec metadata for the selected version (i.e., modifies and compiles the methods with the #packages:attribute: pragma for the appropriate version to match the currently loaded Monticello package versions). After the methods are update you are prompted to Save Project.
Update Package Repositories
Updates the repository group for each Monitcello package associated with the selected version of the Metacello project to include the repository for that package as specified in the version spec.
[Update 8-26-2009 … more information, if not clearer explanation] When I use Metacello to bootstrap the GemStone Seaside extent, I have TrueRepositories turned off, because I am loading from a disk-based repository (using repositoryOverrides in the loader) so that we don’t _have_ to hit the http repository for every GemStone product build (and for folks using GLASS behind corporate firewalls that don’t have direct access to HTPP repositories). As a result the repositoryGroup is empty for each of the packages. This is a real pain when you start doing development.
‘Update Package Repositories’ scans every package and adds the project repository to the repositoryGroup for each package, so that one doesn’t have to manually do so.
Current Project Version
Displays the current version of the selected Metacello project. The version is calculated by comparing the currently loaded Monticello packages to those specified in the version spec. A leading ‘~’ means that the version is partially loaded (i.e., not all of the packages associated with the project have been loaded into the image).
Load Project Version
Prompts for the version of the selected Metacello project to be loaded. If there are groups associated with the selected version, you are prompted for the group that you would like loaded. When in doubt choose ‘ALL’.
Save Project
Saves the selected Metacello project to the repository specified by the project package of the selected version. You are prompted for version name and commit comment.
Update Project
Loads the latest Monticello package version from the repository specified in the project package of the selected version of the Metacello project. Remember that you are simply loading the Metacello project metadata, so it doesn’t hurt to have the latest metadata loaded. Once the latest version is loaded, you are prompted to Load Project Version.
GLASS Configuration
[Update: 10/14/2009] Note that the information is out-of-date in this section relative to newer versions of Metacello. Please see this post for more up-to-date information.
With Metacello, the configuration of the GLASS appliance goes from this incomprehensible (and pratically uneditable) list of packages:
to a manageable list of Metacello project references:
Best of all, it becomes possible to load a project like Pier into a minimal base image (with only Monticello, Metacllo and OB loaded) using something like the following expression:
(GsPierMetacelloProject version: '1.2') load: { 'Pier Core'. 'Pier AddOns'. }
Not only does Pier get loaded, but all of the projects that Pier depends upon (i.e., Magritte, Seaside, Scriptaculous, etc.) get loaded along with the projects that they depend upon.
For the curious, here are the definitions of the ‘Pier Core’ and ‘Pier AddOns’ groups:
Bootstrapping Metacello
[Update: 10/14/2009] Please see this new section for loading Metacello into an image.
To use Metacello in GLASS, modifications to some base classes are needed, so you will have to wait until I publish a GLASS package to bootstrap Metacello into GLASS.
To bootstrap Metacello into Squeak or Pharo:
- Load Metacello-All-dkh.10 from http://seaside.gemstone.com/ss/metacello (loads
Metacello-Core, Metacello-MC, MetacelloProject and OB-Metacello – note that
Metacello-All needs to have a fairly recent version of OB loaded. - Delete the Metacello-All package. It’s only needed to bootstrap Metacello.
- Execute the following expression in a workspace to load the latest version:
MetacelloMetacelloProject updateProject. MetacelloMetacelloProject latestVersion load.
The #updateProject method performs an Update Project to ensure that you have the most recent Metacello project metadata. The #latestVersion method finds the latest non-development version of Metacello (currently 0.15). The #load method then loads the ‘DEFAULT’ packages for the latest version.
The ‘DEFAULT’ group specifies the bare minimum of packages needed to use Metacello (‘Metacello-Core’, ‘Metacello-MC’, ‘Metacello-Platform’, and ‘OB-Metacello’).
The ‘Tests’ group specifies the unit test packages for Metacello.
The ‘Samples’ group specifies the package containing some sample Metacello projects including samples for Seaside2.8 and Seaside2.9.
The ‘Tutorial’ group specifies the package containing the Metacello tutorial.
To load the whole Metacello enchilada, you’d execute the following expression:
MetacelloMetacelloProject updateProject.
MetacelloMetacelloProject latestVersion load: 'ALL'.
Tutorial
[Update: 10/14/2009] Please see this new section for loading the Metacello tutorial into an image.
The tutorial covers all of the important Metacello features in some detail. To load the tutorial, execute the following expression:
MetacelloMetacelloProject updateProject.
MetacelloMetacelloProject latestVersion load: 'Tutorial'.
Then open two class browsers on the MetacelloTutorialProject class. In the left hand browser view the methods in the ‘lessons’ category. In the right hand browser view the ‘–all–‘ category. Read the comments in lesson01 through lesson16OtherExamples.
Current Status
[Update: 10/14/2009] Please see this new section for the current status of the Metacello project.
Version 0.15, the curent version of Metacello, is feature complete, but I’m chasing down infant mortality bugs while I am creating the Metacello projects for GLASS. Once I’m happy, I will release a beta version of Metacello along with the final GLASS package which will boot Metacello into GLASS.
A Metacello Users Guide is also in the works and should be available soon.
—–
[1]Photo by kruemi (Creative Commons).
10 comments
Comments feed for this article
August 26, 2009 at 2:22 pm
Mike Roberts
Dale, managed to get this loaded into Pharo. Great stuff!
–Mike
August 26, 2009 at 3:18 pm
Dale Henrichs
Thanks,
It seems to be scratching an itch I’ve had for a long time, so I’m hopeful that other folks will benefit as well.
August 29, 2009 at 1:08 pm
Germán Arduino
Very interesting work Dale! I’m curious in know if you considered some existent squeak tools previous to decide to develop your own package manage system.
Thanks by share!
August 29, 2009 at 3:03 pm
Dale Henrichs
Germán, I looked at a couple of tools, but didn’t see anything that had the features that I thought I wanted (and was able to get in Metacello). I didn’t do an exhaustive search, because I figured that if there was a real good answer, then it would be in general use (like Monticello is in general use).
If there are some specific tools that you are thinking of then I’d be interested in hearing about them …
August 29, 2009 at 3:46 pm
Germán Arduino
Not, not thinking on nothing specific, just having the same feeling than you (a lot of tools around (Monticello, Squeaksource, Universes, Installer, Sake, LPF, etc, etc -1-)) but none doing the things that a package manager should do.
I’m so interested in learn/try Metacello to have only one tool to manage source code. May be that could help also on the process of build/release the Squeak image, that is now being discussed (from some time ago pushed by Andreas).
Are you already on Brest? Good luck and publish pics of ESUG! :)
-1- Ok, I know aren’t all to the same things, but all related with source code management.
August 29, 2009 at 6:37 pm
Dale Henrichs
Germán, I think that with the tools you mentioned, one can do package management, but each of them seem to miss one piece or another of the puzzle…I know that Metacello is making the the build/release cycle for GLASS much easier … I’ve got some GLASS-specific release tools that I’m using (that can be adapted for Squeak/Pharo), that use the Metacello metadata for generating build scripts and the like …
September 9, 2009 at 11:21 am
Fruit de ESUG 2009 « (gem)Stone Soup
[…] I feel comfortable with the core engine of Metacello, I arrived in Brest, keen to get feedback on the spec creation API. Fortunately, I was able to […]
October 14, 2009 at 5:23 pm
A Shiny New API for Metacello « (gem)Stone Soup
[…] new API is completely different than the API described in my previous post: Metacello: Package Management for Monticello. The basic concepts and functionality hasn’t changed, but the details of the API have been […]
March 23, 2010 at 1:08 pm
GLASS Beta Update: Metacello, GemTools, GLASS, Cha, Cha, Cha « (gem)Stone Soup
[…] me that the days were numbered for the GLASS.230-dkh umbrella package and that I would have to find a better solution for making releases in Smalltalk. I just didn’t realize that the number would top […]
November 18, 2011 at 3:37 pm
GemTools 1.0-beta.8.6 « (gem)Stone Soup
[…] upgrade process has been greatly simplified since I first started using Metacello for bootstrapping GLASS 1.0-beta.0, back in November of 2009, but the basic steps have remained the […]