Squeak
  links to this page:    
View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide
Make a compact model of your package ecosystem
Last updated at 9:02 pm UTC on 1 September 2019

A new, orthogonal subclass hierarchy

The subclasses of Installer have traditionally been to vary the technical implementation of interfacing to the many various packaging systems that have been developed by the community. Now, a new subclass hierarchy is emerging which leverages configuration with Monticello, Squeak's defacto SCM tool which began about 2005.

A terse representation

The idea is to provide the user a way to essentially just list the load order of packages as a Smalltalk Array literal, and the symbolic name of the repository and project directory they reside at. For example, Installer>>#ffi is:
ffi
	"Foreign Function Interface."
	^ { #squeak -> 'FFI'.
	'FFI-Pools'.
	'FFI-Kernel' }

The first line is a directive which sets the "current repository" and project directory where the package names that follow can be found. Browse implementors of #squeak to see that it refers to the Repository at 'source.squeak.org'.

Now, take a look at Installer>>#ffiTests.
ffiTests
	"Tests for Foreign Function Interface."
	^ { self ffi.
	#squeak -> 'FFI'.
	'FFI-Tests' }

ffiTests requires ffi, of course. Note the first line. It continues the flat-list metaphor and very easy for the user to write and understand, but evaluating to an inner Array specification as the first element. The system employs a recursive depth-first enumeration on this to implement several configuration use cases.

(Note: In ffiTests, above, its recommended to always specify the repository immediately preceding the package names, even though we know they're the same as #ffi, we don't want to count on that).

Loading code

The most basic use case is merging entire suites of packages, without disrupting any changes to existing packages even if they should be part of the new load. For example, if first you executed:
  Installer new merge: #ffi

And then made some local changes to FFI, wanted to see if anything broke, so load #ffiTests. Further, pretend someone else had since made a new version of FFI, then executing:
  Installer new merge: #ffiTests

would merge the new version without disturbing local changes when it loaded ffiTests.

Integrating local work on remote packages

When working on improving code in packages, it is often desirable to work with them from one's own local repositories. The easiest way to do this is:
  Installer useLocalRepository


If, however, you had already loaded a package from remote repository, then all of the packages will only have the remote repository added to each WorkingCopy. Instead of having to add your local directory to each one, you can simply:
  Installer addLocalRepositories


Note: for finer control, the symbolic repository specifications can be overridden like:
  Installer
    overrideRepository: #squeak
    with: #local

Project-specific overrides are also supported:
  Installer
    overrideRepository: #squeak->'FFI'
    with: #local


  1. local refers to the repository defined by Installer class>>#localRepository, which defaults to a directory named 'mc' in the working directory, which can be overridden if necessary.

The overrides may either be symbolic or the actual MCRepository instances.

Automatic Repository configuration for WorkingCopy's

When merging #ffi, above, the repository's were loaded from are added automatically to each WorkingCopy loaded. If you installed them from local repositories and want to save them to remote repositories, the WorkingCopy's can be added via:
  Installer addRemoteRepositories.

Whereas, if you installed them from remote repositories but now decide you want to work on them in your local, the locals can be added via:
  Installer addLocalRepositories.


(The above two may now both be being done automatically in some cases).

Publish latest local versions

Every once in a while, its nice to publish the latest version of each package to their various repositories. This can be done like this:
  MyInstaller new
    copyLocalVersionsToRemoteFor: #myPackage
    id: idString
    password: pwString


It does not make any new Versions, it only copies the latest existing Version of each package to its remote repository defined in its package-definitions method.

Seamless Partition between proprietary and public code

Subclasses of Installer can reside in their own private packages and provide their own package-definitions for proprietary applications. For example:
  Installer
    MaInstaller
      MaCommercialInstaller
        HaeInstaller          "<--- client-specific"
        MyInstaller

Each defines its own method category, 'package-definitions', which is a special category where the package lists are put:.
InstallerBase Squeak packages #(connectors curvedSpaceExplorer ffi ffiTests htmlValidator jsonParser maInstalller mathMorphs...)
MaInstallerMy public open-source projects #(base serializer clientServer magmaClient magmaServer maUi)
MaCommercialInstallerMy proprietary closed-source projects #(geoSupport geoNamesCore geoNamesMaui kmlCore kmlMaui tephraCore tephraMaui)
HaeInstallerClient-specific package-definitions.
MyInstallerMy personal projects which are not shared.

How-To

By creating your own subclass of Installer which organize your own public and proprietary packages, you too can enjoy the configuration conveniences afforded by this simple, terse representation. It is not intended to replace any other system like Metacello, Git, SqueakMap or anything. It's just a cheap and terse way to model Squeak packages into a hierarchy for easy access and configuration.