Digging in the Dark[1]

Metacello 1.0-beta.28 was released this morning. Here is a sampling of the of the Metacello 1.0-beta.28 features:

  • introduction of symbolic versions
  • improved scripting and tools support with MetacelloToolBox class
  • 5x speedup in #currentVersion calculation
  • OB-Tools ported to Pharo1.2
  • tutorials ported to ProfStef
  • improved HelpSystem documentation
  • and more

The rest of this post is dedicated to covering symbolic versions and the Metacello Toolbox API in more detail:

Symbolic Versions

Introduction

As Pharo has moved forward from Pharo1.0 to Pharo1.1 to Pharo1.2, aggressively cleaning up the protocol in the base image, it has become difficult to know which version of a configuration to use in a particular version of Pharo. While some folks are pushing the envelope and getting the latest versions of a package to run in Pharo1.2, other folks are trying to go into production using Pharo1.1 or Pharo1.0 and need to use versions of the package that will work in the version of Pharo that they are using.

ConfigurationOfOmniBrowser provides a good example of the problem:

  • version ‘1.1.3’ is used in the Pharo1.0 one-click image
  • version ‘1.1.3’ cannot be loaded into Pharo1.2.
  • version ‘1.2.3’ is currently the latest #development version aimed at Pharo1.2
  • version ‘1.2.3’ cannot be loaded into Pharo1.0

Obviously version ‘1.1.3’ should be used in Pharo1.0 and version ‘1.2.3’ should be used in Pharo1.2, but there is no way for a developer to communicate this information to his users using Metacello.

Over the course of last summer and into the fall we considered number of different solutions for this problem including:

Finally at ESUG I got a chance to meet face to face with a whole group of Pharo folks to talk over different ideas, Mariano summarized the results of the discussion.

I finally settled on the idea of a ‘conditional named version’ where one defines a new kind of version in terms of the existing literal versions (like ‘1.1.3’, .1.1.5′, and ‘1.2.3’) and new project attributes (like #’pharo1.0.x’, #’pharo1.1.x’, and #’pharo1.2.x’ that correspond to platform versions). This new kind of version came to be called a symbolic version and was initially discussed in this thread.

Symbolic versions are specified using the symbolic version pragma:

stable: spec
    <symbolicVersion: #'stable'>
    spec for: #'pharo1.0.x' version: '1.1.3'.
    spec for: #'pharo1.1.x' version: '1.1.5'.
    spec for: #'pharo1.2.x' version: '1.2.3'.

Symbolic versions can be used anywhere that a literal version can be used. From a load statement:

(ConfigurationOfOmniBrowser project version: #'stable') load.

to a project reference versionString  in a baseline version:

baseline10: spec
  <version: '1.0-baseline'>
  spec for: #squeakCommon do: [
    spec blessing: #baseline.
    spec repository: 'http://seaside.gemstone.com/ss/GLASSClient'.
    spec
      project: 'OmniBrowser' with: [
        spec
          className: 'OmniBrowser';
          versionString: #'stable';
          repository: 'http://www.squeaksource.com/MetacelloRepository' ].
    spec
       package: 'OB-SUnitGUI' with: [
         spec requires: #( 'OmniBrowser') ];
       package: 'GemTools-Client' with: [
         spec requires: #( 'OB-SUnitGUI'. ) ];
       package: 'GemTools-Platform' with: [
         spec requires: #( 'GemTools-Client'. ) ]].

New Platform Version Attributes

New attributes have been added to Metacello for Pharo and Squeak to correspond to platform versions:

  • #’pharo1.x’, #’pharo1.0.x’, #’pharo1.1.x’, and #’pharo1.2.x’
  • #’squeak3.10.x’, #’squeak4.x’, #’squeak4.1.x’, and #’squeak4.2.x’

These new attributes are calculated by default in Metacello based on `SystemVersion current version`. If you need a finer grain distinction for versions (say an attribute named #’pharo1.1.1′ to manage conditional code that is specific to Pharo1.1.1) then you can change the #project method in your configuration to something like the following:

project
  | versionString projectAttributes |
  ^ project
    ifNil: [
      "Bootstrap Metacello if it is not already loaded"
      self class ensureMetacello.
      "Construct Metacello project"
      project := (Smalltalk at: #MetacelloMCProject) new.
      projectAttributes := #().
      Smalltalk
        at: #SystemVersion
        ifPresent: [ :cl |
          versionString := cl current version.
          ((versionString beginsWith: 'Pharo-1.1.1')
              or: [ versionString beginsWith: 'Pharo1.1.1' ])
            ifTrue: [ projectAttributes add: #'pharo1.1.x' ] ].
      project projectAttributes: projectAttributes.
      (Smalltalk at: #MetacelloVersionConstructor) on: self project: project.
      project loadType: #linear ]

Standard Symbolic Versions

A couple of standard symbolic versions have already been defined:

  • bleedingEdge – A symbolic version that specifies the latest mcz files and project versions. By default the #bleedingEdge symbolic version is defined as the latest baseline version available. The default specification for #bleedingEdge is defined for all projects. The #bleedingEdge version is primarily for developers who know what they are doing. There are no guarantees that the #bleedingEdge version will even load, let alone function correctly.
  • development – A symbolic version that specifies the literal version that us under development (i.e., whose blessing is #development). Typically a #development version is used by developers for managing pre-release activities as the project transitions from #bleedingEdge to #stable. There are a number of MetacelloToolBox methods that take advantage of the #development symbolic version.
  • stable – A symbolic version specifies the stable literal version for a particular platform. The #stable version is the version that should be used for loading.

With the exception of the #bleedingEdge version (which has a pre-defined default defined), #stable and/or #development symbolic version information has to be explicitly added to a configuration.

Script and Tool Support

With this release, I’ve added two new classes (among others): MetacelloBaseConfiguration and MetacelloToolBox, which should make developing with Metacello and writing tools for Metacello a whole lot easier.

Development Support

The MetacelloBaseConfiguration class is aimed at eventually becoming the common superclass for all Metacello configurations, but I’m not quite ready to go there, yet. For now, though, the class serves as the location for defining the common default symbolic versions (#bleedingEdge at the present time) and as the place to find development support methods:

  • compareVersions – Compare the #stable version to #development version.
  • createNewBaselineVersion – Create a new baseline version based upon the #stable version as a model.
  • createNewDevelopmentVersion – Create a new #development version using the #stable version as model.
  • releaseDevelopmentVersion: – Release #development version: set version blessing to #release, update the #development and #stable symbolic version methods and save the configuration.
  • saveConfiguration: – Save the mcz file that contains the configuration to it’s repository.
  • saveModifiedPackagesAndConfiguration: – Save modified mcz files, update the #development version and then save the configuration.
  • updateToLatestPackageVersions: – Update the #development version to match currently loaded mcz files.
  • validate – Check the configuration for Errors, Critical Warnings, and Warnings.

I suggest that you take a look at these methods and copy the methods that you find useful to the class-side of your own configuration, so that you can simplify the management of your own configuration.

For more information about how the above methods may be used in your project read through the Development Cycle Walk Through.

Metacello Toolbox API

The MetacelloToolBox class is aimed at providing a common API for development scripts and Metacello tools. The development support methods were implemented using the Metacello Toolbox API and the OB-Metacello tools have been reimplemented to use the Metacello Toolbox API. For an overview of the Metacello Toolbox API, you can look in the HelpBrowser at the ‘Metacello>>API Documentation’ section.

The instance-side methods for MetacelloToolBox support the  programmatic editing of Metacello configurations from the creation of a new configuration classes to the creation and changing of literal and symbolic version methods. The instance-side methods are intended for the use of Tools developers and are covered in the ProfStef tutorial: ‘Inside Metacello Toolbox API’.

The class-side methods for MetacelloToolBox support a number of configuration management tasks beyond the development support methods.

The target the initial release of the Metacello Toolbox API is to support the basic Metacello development cycle. In addition to the following section the Metacello development cycle is covered in the ProfStef tutorial: ‘Metacello Development Cycle’.

Development Cycle Walk Through

In this section we’ll take a walk through a typical development cycle and provide examples of how the Metacello Toolbox API can be used to support your development process:

  1. Example Setup
  2. Project Startup
    1. Create Configuration and Initial Baseline
    2. Create Initial Literal Version
    3. Validation
    4. Save Initial Configuration
  3. Development Cycle
    1. Platform Testing
    2. Release
    3. Open New Version for Development
    4. Configuration Checkpoints
    5. Update Project Structure
    6. and Repeat…

1.0 Example Setup

When you are developing your project and are building your configuration for the first time, you already have the packages that make up your project loaded and correctly running on your image. In this example,it is necessary to load a set of packages to simulate a image that will be used to build the first configuration of the project. We’ll cheat here an use an existing configuration (ConfigurationOfGemTools) to download and install in our image all the packages and dependencies needed (just as we would have to do by hand if we were the maintainers of the project). So, don’t pay much attention to this step and only focus on the fact that after evaluating it, you’ll have loaded in your image all the packages needed to build the example configuration:

Gofer new
  squeaksource: 'MetacelloRepository';
  package: 'ConfigurationOfGemTools';
  load.
((Smalltalk at: #ConfigurationOfGemTools) project version: '1.0-beta.8.3')
  load: 'ALL'.

GemTools is expected to work in Squeak (Squeak3.10 and Squeak4.1) and Pharo (Pharo1.0 and Pharo1.1) and depends upon 4 other projects:

  • FFI
  • OmniBrowser
  • Shout
  • HelpSystem

GemTools itself is made up of 5 mcz files from the http://seaside.gemstone.com/ss/GLASSClient repository (note that I’ve made some minor structural changes to simplify the example):

  • OB-SUnitGUI – requires ‘OmniBrowser’. in ‘default’ group.
  • GemTools-Client – requires ‘OmniBrowser’, ‘FFI’, ‘Shout’, and ‘OB-SUnitGUI’. in ‘default’ group.
  • GemTools-Platform – requires ‘GemTools-Client’. in ‘default’ group.
  • GemTools-Help – requires ‘HelpSystem’ and ‘GemTools-Client’. in ‘default’ group.

2.0 Project Startup

2.1 Create Configuration and Initial Baseline

Use the toolbox API to create the initial baseline version by specifying the name, repository, projects, packages, dependencyMap and group composition (see method comment for explanations of arguments):

  MetacelloToolBox
    createBaseline: '1.0-baseline'
    for: 'GemToolsExample'
    repository: 'http://seaside.gemstone.com/ss/GLASSClient'
    requiredProjects: #('FFI' 'OmniBrowser' 'Shout' 'HelpSystem')
    packages: #('OB-SUnitGUI' 'GemTools-Client' 'GemTools-Platform' 
            'GemTools-Help' )
    dependencies:
      {('OB-SUnitGUI' -> #( 'OmniBrowser' )).
      ('GemTools-Client' -> #( 'OmniBrowser' 'FFI' 'Shout' 'OB-SUnitGUI' )).
      ('GemTools-Platform' -> #( 'GemTools-Client' )).
      ('GemTools-Help' -> #( 'HelpSystem' 'GemTools-Client' )). }
    groups:
      {('default' -> #( 'OB-SUnitGUI' 'GemTools-Client' 'GemTools-Platform'
            'GemTools-Help' ))}.

The #createBaseline:… method copies the class MetacelloConfigTemplate to a class named ConfigurationOfGemToolsExample and creates a #baseline10: method that looks like the following:

baseline10: spec
  <version: '1.0-baseline'>
  spec for: #'common' do: [
    spec blessing: #'baseline'.
    spec repository: 'http://seaside.gemstone.com/ss/GLASSClient'.
    spec
      project: 'FFI' with: [
        spec
          className: 'ConfigurationOfFFI';
          versionString: #'bleedingEdge';
          repository: 'http://www.squeaksource.com/MetacelloRepository' ];
      project: 'OmniBrowser' with: [
        spec
          className: 'ConfigurationOfOmniBrowser';
          versionString: #'stable';
          repository: 'http://www.squeaksource.com/MetacelloRepository' ];
      project: 'Shout' with: [
        spec
          className: 'ConfigurationOfShout';
          versionString: #'stable';
          repository: 'http://www.squeaksource.com/MetacelloRepository' ];
      project: 'HelpSystem' with: [
        spec
          className: 'ConfigurationOfHelpSystem';
          versionString: #'stable';
          repository: 'http://www.squeaksource.com/MetacelloRepository' ].
    spec
      package: 'OB-SUnitGUI' with: [
        spec requires: #('OmniBrowser' ). ];
      package: 'GemTools-Client' with: [
        spec requires: #('OmniBrowser' 'FFI' 'Shout' 'OB-SUnitGUI' ). ];
      package: 'GemTools-Platform' with: [
        spec requires: #('GemTools-Client' ). ];
      package: 'GemTools-Help' with: [
        spec requires: #('HelpSystem' 'GemTools-Client' ). ].
    spec group: 'default' with: #('OB-SUnitGUI' 'GemTools-Client'
          'GemTools-Platform' 'GemTools-Help' ). ].

Note that for the ‘FFI’ project the versionString is #bleedingEdge, while the versionString for the other projects is #’stable’. At the time of this writing the FFI project did not have a #stable symbolic version defined, so the default versionString is set to #bleedingEdge. If a #stable symbolic version is defined for the project, the the default versionString is #stable. There are no special version dependencies for the GemTools project so the defaults will work just fine.

2.2 Create Initial Literal Version

Now we use the toolbox API to create the  initial literal version for the project. This toolbox method bases the definition of the literal version on the baseline version that we created above and uses the currently loaded state of the image to define the project versions and mcz file versions:

  MetacelloToolBox
    createDevelopment: '1.0'
    for: 'GemToolsExample'
    importFromBaseline: '1.0-baseline'
    description: 'initial development version'.

The #createDevelopment:… method creates a #version10: method in the configuration that looks like this:

version10: spec
  <version: '1.0' imports: #('1.0-baseline' )>
  spec for: #'common' do: [
    spec blessing: #'development'.
    spec description: 'initial development version'.
    spec author: 'dkh'.
    spec timestamp: '1/12/2011 12:29'.
    spec 
      project: 'FFI' with: '1.2';
      project: 'OmniBrowser' with: #'stable';
      project: 'Shout' with: #'stable';
      project: 'HelpSystem' with: #'stable'.
    spec
      package: 'OB-SUnitGUI' with: 'OB-SUnitGUI-dkh.52';
      package: 'GemTools-Client' with: 'GemTools-Client-NorbertHartl.544';
      package: 'GemTools-Platform' with: 'GemTools-Platform.pharo10beta-dkh.5';
      package: 'GemTools-Help' with: 'GemTools-Help-DaleHenrichs.24'. ].

Note that when the #stable symbolic version specifications are carried through into the literal version. If there is no #stable version, then the currentVersion of the project is used (as in the ‘FFI’ project), just as the current version of each mcz file is set for the packages.

Note also that the blessing of version ‘1.0’ is set to #development. By setting the blessing of a newly created version to #development, you indicate that the version is under development and is subject to change without notice.

The #createDevelopment:… method also creates (or updates) a #development: method and specifies that version ‘1.0’ is the #development symbolic version:

development: spec
  <symbolicVersion: #'development'>
  spec for: #'common' version: '1.0'.
2.3 Validation

Whenever you finish editing a configuration you should validate it to check for mistakes that may cause problems later on by executing the following expression:

(MetacelloToolBox validateConfiguration: ConfigurationOfGemToolsExample) explore.

If the list comes back empty then you are clean. Otherwise you should address the validation issues that show up.

Validation issues are divided into three categories:

  • Warning – issues that point out oddities in the definition of a version that do not affect behavior.
  • Critical Warning – issues that identify inconsistencies in the definition of a version that may result in unexpected behavior.
  • Error – issues that identify explicit problems in the definition of a version that will result in errors if an attempt is made to resolve the version.

Here’s an example of a Critical Warning validation issue:

Critical Warning: No version specified for the project reference 'OCompletion'
            in version '1.1'
    { noVersionSpecified }
    [ ConfigurationOfOmniBrowser #validateVersionSpec: ]

The first and second line is the explanation, a human readable error message. The third line is the reasonCode, a symbol that represents the category of the issue. You can look up the meanings of the various reasonCodes online or with the following toolbox call:

(MetacelloToolBox descriptionForValidationReasonCode: #noVersionSpecified)
    inspect.

The fourth line lists the configurationClass, the name of the configuration that spawned the issue and the callSite, which is the name of the validation method that generated the error (this is used mainly for debugging).

2.4 Save Initial Configuration

The first time you save your configuration, you have to decide which repository to use. It makes sense to stoe the configuration in your development repository. The first time that you save your configuration you need to use the MonticelloBrowser or an expression like the following:

  Gofer new
    url: 'http://www.example.com/GemToolsRepository';
    package: 'ConfigurationOfGemToolsExample';
    commit: 'Initial version of configuration'.

3.0 Development Cycle

3.1 Platform Testing

Before releasing a configuration, you need to do some tests where you load the configuration on your intended platforms. For GemTools I generally do a test load using a fresh PharoCore image (one for each for each stable version of Pharo) and a fresh Squeak4.1 image with the following load expression:

Gofer new
  url: 'http://www.example.com/GemToolsRepository';
  package: 'ConfigurationOfGemToolsExample';
  load.
((Smalltalk at: #ConfigurationOfGemToolsExample)
    project version: #development) load.

and then I run the unit tests. Note that for the GemTools unit tests you need to have GemStone installed.

3.2 Release

Once you are satisfied that the configuration loads correctly on your target platforms, you can release the #development into production using the following toolbox expression:

  MetacelloToolBox
    releaseDevelopmentVersionIn: ConfigurationOfGemToolsExample
    description: '- release version 1.0'.

The toolbox method #releaseDevelopmentVersionIn:… does the following:

  1. set the blessing of the #development version to #release
  2. sets the #development symbolic version to #notDefined
  3. sets the #stable symbolic version to the literal version of the #development version (in this case ‘1.0’)
  4. saves the configuration mcz file to the correct repository

The #development: method ends up looking like this:

development: spec
  <symbolicVersion: #'development'>
  spec for: #'common' version: #'notDefined'.

The #stable: method ends up looking like this:

stable: spec
  <symbolicVersion: #'stable'>
  spec for: #'common' version: '1.0'.

Finally you can copy the configuration to the MetacelloRepository using the following expression:

  MetacelloToolBox
    copyConfiguration: ConfigurationOfGemToolsExample
    to: 'http://www.squeaksource.com/MetacelloRepository'.
3.3 Open New Version for Development

When you are ready to start another round of development you will need to open a new #development version to record your changes. Before we do that, let’s simulate development by loading a newer version of GemTools into our image:

(ConfigurationOfGemTools project version: '1.0-beta.8.4')
  load: 'ALL'.

Now we can generate a the new development version using this toolbox method:

MetacelloToolBox
  createNewDevelopmentVersionIn: ConfigurationOfGemToolsExample
  description: '- open 1.1 for development'.

The toolbox method #createNewDevelopmentVersionIn:…. takes the versionNumber of the #stable version (‘1.0’) and increments the minor version number to produce the new version number (‘1.1’). Here’s what the #version11: method looks like:

version11: spec
  <version: '1.1' imports: #('1.0-baseline' )>
  spec for: #'common' do: [
    spec blessing: #'development'.
    spec description: ''.
    spec author: 'dkh'.
    spec timestamp: '1/14/2011 11:04'.
    spec
      project: 'FFI' with: '1.2';
      project: 'OmniBrowser' with: #'stable';
      project: 'Shout' with: #'stable';
      project: 'HelpSystem' with: #'stable'.
    spec
      package: 'OB-SUnitGUI' with: 'OB-SUnitGUI-dkh.52';
      package: 'GemTools-Client' with: 'GemTools-Client-DaleHenrichs.559';
      package: 'GemTools-Platform'
        with: 'GemTools-Platform.pharo10beta-DaleHenrichs.7';
      package: 'GemTools-Help' with: 'GemTools-Help-DaleHenrichs.26'. ].

If you look closely you will see that there are new versions of the ‘GemTools-Client’, ‘GemTools-Platform’, and ‘GemTools-Help’ mcz files (that correspond to the newly loaded files).

But who wants to look closely? You can use the following toolbox method to get the differences between the #stable version and the #development version:

(MetacelloToolBox compareVersionsIn: ConfigurationOfGemToolsExample) printString.

Which results in the following difference report:

ConfigurationOfGemToolsExample '1.0' to '1.1'
  Additions:
  Modifications:
    GemTools-Help
      'GemTools-Help-DaleHenrichs.24' to 'GemTools-Help-DaleHenrichs.26'
    GemTools-Platform
      'GemTools-Platform.pharo10beta-dkh.5' to
              'GemTools-Platform.pharo10beta-DaleHenrichs.7'
    GemTools-Client
      'GemTools-Client-NorbertHartl.544' to 'GemTools-Client-DaleHenrichs.559'
  Removals:
3.4 Configuration Checkpoints

Over the course of development there are several different checkpoint scenarios for saving the configuration and the mcz files for the project:

Update Configuration
MetacelloToolBox
  updateToLatestPackageVersionsIn: ConfigurationOfGemToolsExample
  description: '- fixed Issue 1090'.
Save Modified Packages and Update Configuration
MetacelloToolBox
  saveModifiedPackagesIn: ConfigurationOfGemToolsExample
  description: '- fixed Issue 1090'.
Save Modified Packages, Update and Save Configuration
MetacelloToolBox
  saveModifiedPackagesAndConfigurationIn: ConfigurationOfGemToolsExample
  description: '- fixed Issue 1090'.
Save Configuration
MetacelloToolBox
  saveConfigurationPackageFor: 'GemToolsExample'
  description: '- fixed Issue 1090'.
3.5 Update Project Structure

In the course of development it is sometimes necessary to add a new package or reference an additional project. These changes will necessitate the creation of a new baseline version.

For our example let’s add a package to the project called ‘GemTools-Overrides’ (‘GemTools-Overrides’ is actually part of the GemTools project). Here’s the summary of the changes we want to make:

  • GemTools-Overrides – requires ‘OmniBrowser’.
  • GemTools-Client – requires ‘GemTools-Overrides’

Here’s what we need to do:

  1. create a new baseline version (1.1-baseline) with the new package and updated dependencies
  2. update existing #development version to reference the new baseline version and include the explicit version for the new package

We can manually edit the configuration or use the  folowing toolbox methods to create the baseline version:

MetacelloToolBox
  createNewBaselineVersionIn: ConfigurationOfGemToolsExample
  requiredProjects: #()
  packages: #( 'GemTools-Overrides' )
  dependencies: {
    'GemTools-Overrides' -> #( 'OmniBrowser' ).
    'GemTools-Client' -> #( 'GemTools-Overrides' ). }
  groups: #().

The new #baseline11: method:

baseline11: spec
  <version: '1.1-baseline'>
  spec for: #'common' do: [
    spec blessing: #'baseline'.
    spec repository: 'http://seaside.gemstone.com/ss/GLASSClient'.
    spec
      project: 'FFI' with: [
        spec
          className: 'ConfigurationOfFFI';
          versionString: #'bleedingEdge';
          repository: 'http://www.squeaksource.com/MetacelloRepository' ];
      project: 'OmniBrowser' with: [
        spec
          className: 'ConfigurationOfOmniBrowser';
          versionString: #'stable';
          repository: 'http://www.squeaksource.com/MetacelloRepository' ];
      project: 'Shout' with: [
        spec
          className: 'ConfigurationOfShout';
          versionString: #'stable';
          repository: 'http://www.squeaksource.com/MetacelloRepository' ];
      project: 'HelpSystem' with: [
        spec
          className: 'ConfigurationOfHelpSystem';
          versionString: #'stable';
          repository: 'http://www.squeaksource.com/MetacelloRepository' ].
    spec
      package: 'OB-SUnitGUI' with: [
        spec requires: #('OmniBrowser' ). ];
      package: 'GemTools-Client' with: [
        spec requires: #('OmniBrowser' 'FFI' 'Shout' 'OB-SUnitGUI'
                'GemTools-Overrides' ). ];
      package: 'GemTools-Platform' with: [
        spec requires: #('GemTools-Client' ). ];
      package: 'GemTools-Help' with: [
        spec requires: #('HelpSystem' 'GemTools-Client' ). ];
      package: 'GemTools-Overrides' with: [
        spec requires: #('OmniBrowser' ). ].
    spec group: 'default' with: #('OB-SUnitGUI' 'GemTools-Client'
                'GemTools-Platform' 'GemTools-Help' ). ].

The following method updates the #development version method:

MetacelloToolBox
  modifyDevelopmentVersionIn: ConfigurationOfGemToolsExample
  imports: #('1.1-baseline' )
  requiredProjects: #()
  packages: #('GemTools-Overrides')
  description: '- import from 1.1-baseline and add GemTools-Overrides package'.

The updated #version11: method:

version11: spec
  <version: '1.1' imports: #('1.1-baseline' )>
  spec for: #'common' do: [
    spec blessing: #'development'.
    spec description: '- open 1.1 for development
- import from 1.1-baseline and add GemTools-Overrides package'.
    spec author: 'DaleHenrichs'.
    spec timestamp: '1/15/2011 15:50'.
    spec
      project: 'FFI' with: '1.2';
      project: 'OmniBrowser' with: #'stable';
      project: 'Shout' with: #'stable';
      project: 'HelpSystem' with: #'stable'.
    spec
      package: 'OB-SUnitGUI' with: 'OB-SUnitGUI-dkh.52';
      package: 'GemTools-Client' with: 'GemTools-Client-DaleHenrichs.559';
      package: 'GemTools-Platform'
          with: 'GemTools-Platform.pharo10beta-DaleHenrichs.7';
      package: 'GemTools-Help' with: 'GemTools-Help-DaleHenrichs.26';
      package: 'GemTools-Overrides'
           with: 'GemTools-Overrides-DaleHenrichs.1'. ].

Finally we’ll do a comparison to version 1.0:

(MetacelloToolBox compareVersionsIn: ConfigurationOfGemToolsExample) printString.

Which results in the following difference report:

ConfigurationOfGemToolsExample '1.0' to '1.1'
  Additions:
    GemTools-Overrides '' to
           'GemTools-Overrides-DaleHenrichs.1'
  Modifications:
    GemTools-Help
      'GemTools-Help-DaleHenrichs.24' to 'GemTools-Help-DaleHenrichs.26'
    GemTools-Platform
      'GemTools-Platform.pharo10beta-dkh.5' to
            'GemTools-Platform.pharo10beta-DaleHenrichs.7'
    GemTools-Client
      'GemTools-Client-NorbertHartl.544' to 'GemTools-Client-DaleHenrichs.559'
  Removals:
3.6 and Repeat…

When development is completed you start over with Platform Testing.

Expanded Documentation & Tutorials

Expanded Help Browser documentation (click on image):

Expanded ProfStef tutorials (click on image):

Developer Action Items

The first thing you should do is load up Metacello 1.0-beta.28 and define #stable symbolic versions for your configurations.

Next, you should run the validator against your configurations and fix any of the critical warnings and errors that you may find.

Finally, decide which of the development support methods you’d like to use as part of the development cycle for your configurations.

—–
[1]
Photo by http://www.flickr.com/photos/wessexarchaeology/51568417 / CC BY NC SA 2.0