<!doctype html public "-//W3C//DTD W3 HTML//EN">
<html><head><style type="text/css"><!--
blockquote, dl, ul, ol, li { padding-top: 0 ; padding-bottom: 0 }
 --></style><title>More Installer and Sake/Packages
documentation</title></head><body>
<div>For those who cannot be bothered to look in an Image for
documentation, here are some of the</div>
<div>Class Comments retrieved from an
090628-1523_Squeak3.10.2-lpf-atomic image from &lt;<font
color="#000000"
>ftp://ftp.squeak.org/3.11/Squeak3.10.2-lpf-atomic/latest/</font>&gt;
after executing Installer install: 'Packages'.</div>
<div>This is also being posted to
&lt;http://squeaktipsandtrickswatch.blogspot.com/&gt;.</div>
<div><br></div>
<div>Ken G. Brown</div>
<div><br></div>
<div>--</div>
<div><b>Installer-Core/Installer</b></div>
<div><br></div>
<div>Documentation now available at
http://installer.pbwiki.com/Installer<br>
&nbsp;<br>
useFileIn - flag to load source.st rather than using Monticello</div>
<div><br></div>
<div>--</div>
<div><b>Installer-Core/InstallerMantis</b></div>
<div><br></div>
<div>Search feature is based upon a custom mantis query ceveloped and
maintained by Ken Causey &lt;ken@kencausey.com&gt;<br>
<br>
Installer mantis bugsAll select: [ :ea | ea status = 'testing'
].</div>
<div><br></div>
<div>--</div>
<div><b>Installer-Formats/SARInstaller</b></div>
<div><br></div>
<div>I am an object that handles the loading of SAR (Squeak ARchive)
files.<br>
<br>
A SAR file is a Zip file that follows certain simple conventions:<br>
<br>
* it may have a member named &quot;install/preamble&quot;.<br>
<br>
This member, if present, will be filed in as Smalltalk source code at
the beginning of installation.<br>
Typically, the code in the preamble will make whatever installation
preparations are necessary,<br>
and will then call methods in the &quot;client services&quot; method
category to extract or install other zip members.<br>
<br>
* It may have a member named &quot;install/postscript&quot;.<br>
<br>
This member, if present, will be filed in as Smalltalk source code at
the end of installation.<br>
Typically, the code in the postscript will set up the operating
environment,<br>
and will perhaps put objects in flaps, open projects or README files,
or launch samples.<br>
<br>
Within the code in the preamble and postscript, &quot;self&quot; is
set to the instance of the SARInstaller.<br>
<br>
If neither an &quot;install/preamble&quot; nor an
&quot;install/postscript&quot; file is present,<br>
all the members will be installed after prompting the user,<br>
based on a best guess of the member file types that is based on member
filename extensions.<br>
<br>
This is new behavior.</div>
<div><br></div>
<div>--</div>
<div><b>Installer-Scripts/InstallerScripts</b></div>
<div><br></div>
<div>(self new addPackage: 'Example') options collect: [ :ea&nbsp; |
ea value asLegalSelector asSymbol ]&nbsp;
#(#scriptExampleSqueak310forKPH #scriptExampleSqueak310
#scriptExampleSqueak310)</div>
<div><br></div>
<div>--</div>
<div><b>Installer-Launcher/Launcher</b></div>
<div><br></div>
<div>A Launcher provides squeak with a range of capabilities that are
intended to be used from the command line.<br>
<br>
As a design goal, the startup process can invoke Launcher several
times at several points in the startup sequence. In particular 1)
below aims to provide a mechanism for getting in to images that are
broken in some form, so as to enable a script to be run before morphic
has attempted to startup.<br>
<br>
1) Launcher is registered to handle startup notification after
Security manager<br>
any class which wishes to provide a service to be usable at this time
implements startFrom:<br>
<br>
2) Launcher is wired in to ProjectLauncher to handle startup
notification when squeak is fully initialized. Any class wishing to
provide a service to be usable at this time implements launchFrom:<br>
<br>
#startFrom: and #launchFrom: are called providing a handle to the
launcher which may be used to obtain parameters using the desired
scheme.<br>
<br>
a) launcher getParameters . key=value +yes -no<br>
b) launcher getParametersOldStyle . key value key2 value2<br>
<br>
Instance Variables<br>
<x-tab>&nbsp;&nbsp;&nbsp; </x-tab>actionSelector: #startFrom:
#launchFrom:<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</x-tab>commandLineClass: aClass<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</x-tab>image:<x-tab>&nbsp; </x-tab>the smalltalk image or self if
being a mock<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp; </x-tab>mock: the mock array of
startup parameters<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </x-tab>nextCommandLineDocument:
aString</div>
<div><x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</x-tab>nextParameterIndex:<x-tab>&nbsp;&nbsp;&nbsp;&nbsp; </x-tab>
anInteger<br>
&nbsp;</div>
<div>--</div>
<div><b>Sake-Core/SakeBlock</b></div>
<div><br></div>
<div>Raise this if for some reason you find that the task you are
doing is blocked. This might occur in a multi builder build system
where two building threads decide to build the same item.<br>
<br>
(implementation idea - not implemented yet)<br>
<br>
When a Block is detected, Sake, looks for any following dependent task
that is not dependant upon the blocked task.<br>
</div>
<div>Alternatively, Sake could simply randomise the task order and
re-sort them, tryng again.</div>
<div><br></div>
<div>--</div>
<div><b>Sake-Core/SakeCompiler</b></div>
<div><br></div>
<div>Enables methods to include raw uncompiled text for documentation
purposes following a line containing 6 quotes
&quot;&quot;&quot;&quot;&quot;&quot;</div>
<div><br></div>
<div>--</div>
<div><b>Sake-Core/SakeMeta</b></div>
<div><br></div>
<div>I'm a dictionary which can be used using any method call instead
of #at:put: and at:. Use me like:<br>
<br>
- (aSakeMeta foo: 'bar') which is equivalent to (aSakeMeta at: 'foo'
put: 'bar')<br>
- (aSakeMeta foo) which is equivalent to (aSakeMeta at: 'foo')<br>
<br>
The instance variable 'order' remembers the order in which the
elements have been added. The methods #withIndexDo: and #printOn: use
this variable to iterate in the same order.<br>
<br>
| s |<br>
s := ReadWriteStream on: String new.<br>
(self new a: 1; b: 2; yourself) storeOn: s.<br>
s reset contents<br>
</div>
<div>--</div>
<div><b>Sake-Core/SakeTask</b></div>
<div><br></div>
<div>SakeTasks are typically defined as class side methods, which
return an instance of SakeTask.<br>
<br>
To obtain a list of available tasks, do &quot;Senders of #define:
&quot;<br>
<br>
MyClass-task1: aParameter<br>
<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp; </x-tab>^ SakeTask define: [ :task
|<br>
<x-tab>&nbsp;&nbsp;&nbsp;
</x-tab><x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</x-tab><x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </x-tab>task
dependsOn: {self ruleL3.}.<br>
<x-tab> </x-tab><x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</x-tab><x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </x-tab>task
if: [ &lt;return true if action is needed&gt; ].<br>
<x-tab> </x-tab>&nbsp;&nbsp;&nbsp;&nbsp;<x-tab>&nbsp;&nbsp;&nbsp;
</x-tab>task action: [ &lt;do something&gt; ]<br>
<x-tab> </x-tab>&nbsp; ]<br>
<br>
The 'unique id' of a task is the method context in which it is
instanciated, and its paramters.<br>
Therefore only one task should be instanciated per method.<br>
<br>
Note: Sake tasks can have parameters, Rake tasks dont.<br>
<br>
To execute a task...<br>
<br>
(MyClass task1: 'param') run.<br>
<br>
Results of the prior tasks are available via #results.<br>
<br>
FAQ<br>
====<br>
How can I call one Sake task from inside another task?<br>
<br>
Generally, if you want invoke one task from another task, the proper
way to do that is to include the task to be invoked as a prerequisite
of the task doing the invoking.<br>
<br>
For example:<br>
<br>
MyTasks-c-#taskPrimary<br>
<br>
^ SakeTask define: [ :task |<br>
<x-tab>&nbsp; </x-tab>task dependsOn: { self taskSecondary }.<br>
<x-tab> </x-tab>task action: [ self log sake: 'Doing Primary Task'.
].<br>
]<br>
<br>
MyTasks-c-#taskSecondary<br>
^ SakeTask define: [ :task |<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp; </x-tab>task action: [ self log sake:
'Doing Secondary Task' ].<br>
]<br>
<br>
In this case, if the secondary task fails, the whole task stops.<br>
<br>
Secondary tasks can also be passed to the ifBlock. In that case, if
the task succeeds then the action is performed, if the task fails then
the action is considered not needed.<br>
<br>
^ SakeTask define: [ :task |<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp; </x-tab>task if: { self taskSecondary
}.<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </x-tab>task action:
[ self log sake: 'Doing Primary Task'. ].<br>
]<br>
<br>
Action, can also take a list of tasks.<x-tab>&nbsp;&nbsp; </x-tab><br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </x-tab><br>
^ SakeTask define: [ :task |<br>
<x-tab>&nbsp;&nbsp;&nbsp; </x-tab>task action: {<br>
<x-tab>&nbsp;
</x-tab
>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span
></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self taskSecondary.<br>
<x-tab>&nbsp;&nbsp;&nbsp;
</x-tab
>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span
></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [ self log sake: 'Doing Primary
Task' ].&nbsp; &quot;a block task&quot;<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</x-tab><x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</x-tab><x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</x-tab><x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</x-tab>}<br>
].<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp; </x-tab><br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </x-tab><br>
</div>
<div>--</div>
<div><b>Sake-Packages/Packages</b></div>
<div><br></div>
<div>Sake/Packages usage:<br>
<br>
Definitions Search Path<br>
============================<br>
Packages named: 'PackageName'.<br>
<br>
Will obtain a package definition. Subclasses of Packages are searched
using the order defined by #findPath which is specified by
#priority.<br>
<br>
e.g. Packages findPath =&gt; {PackagesSqueak310 . PackagesDev .
PackagesAll . PackagesSeaside29}<br>
<br>
Packages-#priority is used to sort classes like so:<br>
<br>
The class with defns for a relevant version (listed in
#relevantVersions) =&gt; 100<br>
The class with defns for dev version (PackagesDev) =&gt; 400<br>
The class with defns for all versions (PackagesAll) =&gt; 500<br>
<br>
Additional package &quot;universes&quot; can define their own priority
in order to specify where to appear in the #findPath.<br>
PackagesSeaside29<br>
PackagesGjaller<br>
PackagesBeach<br>
<br>
Usage:<br>
========<br>
verbose usage specifying run style.<br>
<br>
(Packages named: 'Seaside') run.&nbsp; &quot; or runQuietly,
runStepping, runLogging&quot;<br>
<br>
#runStepping , - presents a confirm/debug dialog before each
action.<br>
#run&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- default.<br>
#runQuietly&nbsp;&nbsp;&nbsp; - auto-confirms any SakeConfirm
dialogs.<br>
#runLogging&nbsp;&nbsp; - Writes any SakeStop warnings to self
log.<br>
<br>
default usage:<br>
<br>
Packages load: 'Seaside'.<br>
Packages latest: 'Seaside'. &quot;as above, but use latest versions of
everything&quot;<br>
Packages unload: 'Seaside'.<br>
<br>
multiples:<br>
<br>
Packages load: #('Seaside' 'Magma' 'Logging')&nbsp;<br>
<br>
Unloading<br>
========<br>
Unloading comes in two variants.<br>
<br>
Each package task loaded by Sake/Packages is remembered in the
'provided' list<br>
If you perform:<br>
<br>
&nbsp;&nbsp;&nbsp; Packages unload: 'Seaside' .<br>
<br>
&nbsp;&nbsp;&nbsp; Packages unloadStepping: 'Seaside' .<br>
<br>
Then the 'historical' unload scripts are used, as defined when the
original load tasks were run.</div>
<div><br>
If instead you perform:<br>
<br>
&nbsp;&nbsp;&nbsp; (Packages current named: 'Seaside') beUnloading
runStepping.<br>
&nbsp;<br>
Then the most recently defined unload script will be run.<br>
<br>
Note: If packages such as &quot;Magma server&quot; and &quot;Magma
client&quot; provides &quot;Magma&quot;, then<br>
<br>
&nbsp;&nbsp;&nbsp; Packages unload: 'Magma'.<br>
<br>
Will unload whichever of the two are loaded.<br>
===<br>
Misc notes...<br>
<br>
Universes are using 'instance side' task definition, so the task
extensions mechanism does not work in this context.<br>
<br>
If a package appears in Packages under an obscure name, it can<br>
tell the PackageInfo instance what name was used to load it via
#mcName:<br>
<br>
If a package has a version number with a '+' after it, then 'Packages
upgrade' will always attempt to load the latest code, leaving
Monticello to determine if there are any code changed that need to be
applied.<br>
<br>
To generate all of the methods based upon universes definitions:<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </x-tab><br>
&nbsp;<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </x-tab>Packages
taskGenerateAllUniverses run.<br>
<x-tab>&nbsp; </x-tab>or</div>
<div><x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</x-tab>Packages taskGenerateAll&nbsp; run.</div>
<div><br></div>
<div>--</div>
<div><b>Packages-Library/PackagesDevU</b></div>
<div><br></div>
<div>Package definitions for this version as obtained automatically
from the Universes server.<br>
<br>
To override the definitions in the univere add to my subclass in
PackagesSqueak310<br>
<br>
To re-read the package definitions from the universes server.<br>
<br>
self taskGeneratePackageTasks run</div>
<div><br></div>
<div>--</div>
<div><br></div>
<div><br></div>
</body>
</html>