Basically, Mondrian requires that a version of OmniBrowser is loaded, so the OB dependency is very loose. In the current Mondrian loader, if the class OBNode doesn't exist then the latest version of OmniBrowser is loaded. Instead of making a hard requirement on a specific version of OmniBrowser, I decided to make the requirement conditional on the existence of the class OBNode.
If you recall from the earlier mail on conditional elements, Metacello has a default list of attributes: #common, #squeakCommon, #pharo, #squeak, and #gemstone. When a versionMap is instantiated on a platform, the attribute list is dynamically generated so that on Squeak, the attribute list would be:
#( common squeakCommon squeak)
on Pharo:
#( common squeakCommon pharo)
and on GemStone:
#( common gemstone)
For dynamically creating the package list on Pharo, the attribute list is processed in order. The methods whose pragmas match the pattern:
<packages: * attributes: #common>
are processed creating the initial MetacelloPackageVersionsSpec, then the methods matching this pragma pattern:
<packages: * attributes: #squeakCommon>
are processed and the MetacelloPackageVersionsSpec produced is merged into the initial MetacelloPackageVersionsSpec and so on with #pharo. Similar processing is done for the groups pragmas:
<groups: * attributes: * >
To make the requiredVersion for OmniBrowser conditional, I implemented the method #platformAttributes in MondrianVersionMap:
platformAttributes
| att |
att := super platformAttributes asOrderedCollection.
(Smalltalk hasClassNamed: #OBNode) ifFalse: [ att add: #omnibrowser ].
^att
which adds #omnibrowser to the end of attribute list when the class OBNode is absent. Then by adding a 'conditional' #version01OBGroups method:
version01OBFeatures
<features: '0.1' attribute: #omnibrowser >
^(MetacelloGroupsSpec for: self)
addFeature:
((MetacelloGroupSpec for: self)
groupName: 'core'
description: '';
addMember:
((MetacelloVersionMapSpec for: self)
versionMapClass: 'OBVersionMap';
version: '0.442';
loadList: { 'dev tools'. };
packagesSpec:
((MetacelloPackagesSpec new)
addFile: 'OmniBrowserVersionMap-dkh.2';
addRepository: 'http://seaside.gemstone.com/ss/test';
yourself);
yourself
we can arrange for version '0.442' of the 'dev tools' group from OBVersionMap to be loaded only when the OBNode class is missing.
This technique can avoid a raft of "is this version close enough" troubles.
Dale
because if you got that road you lose the declarative aspects of a
dependency declaration.
In particular it means that it will be more difficult to build tools
that analysis dependency and the rest.
| I have the impression that you can have data that describes a
| situation. Then you can have like in gems a kind of little
| language (<= 3.0)... but my point is that if you have a fixed and more
|
| declarative language then it will be easier after to
| build tools.
| When I looked at Sake (but I may be wrong) I was a bit worried tha
| this is plain smalltalk because you have waht you get a
| full dynamic language.
Okay, this makes sense. I have started looking at RubyGems[1] and they have a set of version operators that I will support (thanks for the prodding). There needs to be a way to specify a dependency that is stricter than 'it is loaded' and looser than 'only this version'. Version numbers by themselves don't provide enough information by themselves but relational operators on versions will be a good start.
Dale