Tag Archives: Metacello

Pharo By Example in Spanish and PBE2 new chapters!

Hi. This is a short post in case someone has missed the info. The Pharo By Example’s spanish translation was finally done. Each of the 14 chapters were translated. Notice that even that, the translation is not 100% ready. It is a draft version and it still needs some passes along the whole book.  Anyway, the link is this: https://gforge.inria.fr/frs/download.php/28829/PBE1-Spanish-FullDraft-2011-08-01.zip

So, please distribute along spanish speaking smaltalkers.

For the translation, there are a lot of people to thank, there were like 15 translators. Special thanks to Gabriala Arevalo who start leading it, and then to Nicolas Paez that continues it.

Besides the translation, Pharo By Example 2 is in the way and there are drafts for already a lot of chapters:

That’s all, I hope you enjoy them.

Advertisements

Loading projects and building your own images with Metacello

As I have already said, I presented at Smalltalks 2011 a talk called “Building your own images with Metacello”. I thought it could be interesting to write down the details of such presentation for those who couldn’t attend or those who want to follow what I did.

Background and Motivations

To help the Pharo community I find myself using new tools (even if they are not completely finished), using/fighting with latest versions (a.k.a bleeding edge), finding/reporting/fixing/testing bugs and issues. So…. I am downloading hundred of images every day. An image can last me a maximum of a couple of days.

Apart from that, after 3 years with Squeak/Pharo I have my own preferences/settings which are different from the defaults. In addition, I often use tools which are not present in the standard Pharo image. I am also working in several projects at the same time. So….. I spend a lot of time building my own images.

If I am downloading hundred of images every day, an image can last me a maximum of a couple of days, and I spend a lot of time building my own images, then there is something that it is not working.

Moreover, I am lazy, I don’t like loosing time with it, and my memory is bad. Hence, I have come to the solution that I will show you in this post.

Types of Operations and Softwares

To explain you what I did, I will use an example my own projects and tools.

Types of Operations

When I am working with Pharo, there are usually 2 types of operations I perform with a particular project: load and build.

Load means that I will just load a project or package into the image where I am working. No more than that. This is useful when I am working with a project with a particular image, and I just want to load another one to see something.

Build, however, not only loads the project or package but also builds my own image for that project. What does it mean to build my own image? well, I install all the tools I use that are not present by default in Pharo, I set my personal settings, etc.

Types of software

There are also 2 types of software: own software and external tools.

Own software are all those projects I own or that I contribute. For these projects, I develop, hence I always want to load the very last version of all packages. In the example of this post, there is Fuel, DBXTalk, Marea and Cog.

External tools are those development tools, addons, themes, or whatever I install when I build my own images. Since I don’t develop these tools, I don’t want the very last version of every package, but instead the last “stable” version. In the example, there are TilingWindowManager,  ‘SimpleLogger’, ‘CodeStats’, ‘Glamoroust’, ‘Keymapping’, ‘SandcastlesThemes’, etc.

Metacello part of the solution

If you have used Metacello before, you are used to see classes like ConfigurationOfSeaside, ConfigurationOfDBXTalk, ConfigurationOfFuel, ConfigurationOfMoose, etc. What I propose is to that you create your own ConfigurationOf. In my case, I have ConfigurationOfMariano. If you want to follow the post watching the real code in your image, then just evaluate:

Gofer new
url: 'http://ss3.gemstone.com/ss/MarianoBuilder';
package: 'MarianoBuilder';
load.

Such configuration has no versions and only one baseline method. The (summary) of such method is:

baseline10: spec
<version: '1.0-baseline'>

spec for: #pharo do: [

spec blessing: #baseline.

" =========================================
The following the list of projects that I DO DEVELOP. Hence, I always want the bleedingEdge, and most of the times, I want to build an image for them.
========================================="

spec
project: 'Fuel' with: [
spec
className: 'ConfigurationOfFuel';
loads: #('DevelopmentGroup' );
file: 'ConfigurationOfFuel';
versionString: #bleedingEdge;
repository: 'http://ss3.gemstone.com/ss/Fuel' ].

spec
project: 'DBXTalk' with: [
spec
className: 'ConfigurationOfGlorpDBX';
loads: #('default' );
file: 'ConfigurationOfGlorpDBX';
versionString: #bleedingEdge;
repository: 'http://www.squeaksource.com/DBXTalk' ].

"....ACTUALLY, THERE ARE MORE PROJECTS...."

" =========================================
The following the list of TOOLS, ADDONS  that I use for my own images. Since they are not my projects, I usually use the latest available metacello version and not the bleedingEdge.
In addition, not all tools and addons are loaded in all type of images I build. Each image decides what to include.
========================================="

spec
project: 'TilingWindowManager' with: [
spec
className: 'ConfigurationOfTilingWindowManager';
loads: #('default');
file: 'ConfigurationOfTilingWindowManager';
repository: 'http://www.squeaksource.com/TilingWindowManager' ].

spec
project: 'Glamoroust' with: [
spec
className: 'ConfigurationOfGlamoroust';
loads: #('GT-Inspector' 'GT-Playground' );
file: 'ConfigurationOfGlamoroust';
repository: 'http://www.squeaksource.com/glamoroust' ].

spec project: 'Keymapping' with: [
spec
className: 'ConfigurationOfKeymapping';
loads: #('forDeveloper' );
file: 'ConfigurationOfKeymapping';
repository: 'http://www.squeaksource.com/ShortWays' ].

"....ACTUALLY, THERE ARE MORE TOOLS...."

" =========================================
The following is a list of groups for building my own images. Notice that for each image group there should be a class side method #buildXXXImage
========================================="

spec
group: 'FuelImage' with: #( 'BaseImage' 'SandcastlesThemes' 'Fuel');
group: 'MareaImage' with: #( 'BaseImage' 'Marea');
group: 'DBXTalkImage' with: #( 'BaseImage' 'DBXTalk');
group: 'CogVMImage' with: #( 'BaseImage' 'CogVM');

group: 'BaseImage' with: #('TilingWindowManager' 'SimpleLogger' 'CodeStats' 'Glamoroust' 'Keymapping').

].

Forget for a moment the last lines about groups. The basic idea is that in such configuration you group both types of software, your own or the one you contribute, and the external tools. There are a couple of interesting things to notice:

  • Whenever I want to install something with Metacello, I never remember whether the ConfigurationOf is in MetacelloRepository or in the same repository of the project. I don’t remember which group/packages I have to load either.  This way such information is stored directly in ConfigurationOfMariano. For example, for Fuel, I have to load ‘DevelopmentGroup’ and the ConfigurationOfFuel is in ‘http://ss3.gemstone.com/ss/Fuel&#8217;. For DBXTalk I have to load ‘default’ and the ConfigurationOfGlorpDBX is in ‘http://www.squeaksource.com/DBXTalk&#8217;. Conclusion? I don’t have to remember that anymore.
  • Notice that for my own projects (Fuel, DBXTalk, Marea, etc) I set #bleedingEdge as the #versionString. This is because of what I have already explained that I always want the last version of each package. In the contrary, for the external tools such as Glamoroust, KeyMapping, etc, I don’t specify anything in #versionString. Hence, the default will be the last stable version, exactly what I want for those cases.

Loading Projects

In the class side of ConfigurationOfMariano there is a category called ‘loading’ and there you can find methods like #loadFuel, #loadDBXTalk, #loadMarea, etc. As an example:

loadFuel
FuelImageBuilder new loadPackages: 'Fuel'

For the moment, forget what FuelImageBuilder does, but imagine it just loads ‘Fuel’ (this is the parameter to #loadPackage:) from ConfigurationOfMariano. Of course, the rest of the #load* methods are the same and they only change the package to load and the builder class.

Conclusion? I can take any Pharo image, Gofer MarianoBuilder and then all I need to do is to send #loadXXX message to ConfigurationOfMariano 🙂 No need to remember anything nor loosing time. In fact what I do is to have  sticky note in my Mac with this code:

Gofer new
url: 'http://ss3.gemstone.com/ss/MarianoBuilder';
package: 'MarianoBuilder';
load.

(Smalltalk at: #ConfigurationOfMariano) perform: #loadFuel.

I copy paste such code and I change #loadFuel for what I want at that moment.

Building my own images

Now let’s see the interesting part. To build your own images with this approach, there are 2 parts. The first part is done in ConfigurationOfMariano. Take a look to the groups defined in the baseline at the beginning of the post.

Basically, we create a Metacello group for each image we want to build. For example, there is a group ‘FuelImage’, ‘DBXTalkImage’, etc. In such groups we can put all external tools that are exclusively needed when we build images for such project. For example, in Fuel I add ‘SandcastlesThemes’ because for Fuel images I want to use such theme. Besides particular tools that each image needs, there is also a group called ‘BaseImage’, where I put all the external tools I want for all images.  In this example, ‘TilingWindowManager’ ‘SimpleLogger’ ‘CodeStats’ ‘Glamoroust’ and ‘Keymapping’.

So…all we do in the baseline of ConfigurationOfMariano related to building images is just to define which packages/projects to load. Now we have to really build the image. Most of the code for building my own images is quite similar among different projects. For example, the code to build a Fuel image will be quite similar to the one to build a DBXTalk image. The image builder is done in Pharo as well so the easiest solution is to use subclassification to customize the build process for each project. The abstract class is GeneralImageBuilder and there are subclasses such as MareaImageBuilder, FuelImageBuilder, DBXTalkImageBuilder, CogVMImageBuilder, etc.

The last part of ConfigurationOfMariano is the class side category called ‘building’, which contains methods such as #buildFuelImage, #buildDBXTalkImage, etc. You can imagine what they do:

buildFuelImage
FuelImageBuilder new buildImage.

The builder

The main method is #buildImage

buildImage
self loadImagePackages.
self generalImagePreferences.
self customPreferences.
self cleanSystem.
self lastActions.
self saveImage.

The first step is to load all the packages defined as part of the image. Each subclass of GeneralImageBuilder understands #imageGroupNameToLoad  which answers the metacello group defined in ConfigurationOfMariano. For example, FuelImageBuilder >> #imageGroupNameToLoad   just answers ‘FuelImage’.

The second line is to set all preferences/settings which are general to all images. Line 3 is a hook that allow subclasses to set custom settings. For example, Fuel and Marea they both set their own background picture, logo, theme, log file name, etc (check implementors of #customPreferences).

With #cleanSystem we execute some cleanings to let the image in a nice and clean state.  Then #lastActions is another hook where each subclass can execute something at the end. For example, to set my username and password for all SqueakSource repositories, to set a global/shared package-cache for all projects, etc.

Finally, we save the image. In my case, I want that the image is saved with a particular name and in a particular place. For example, I want that all Fuel images are called Fuel.N.image and to be placed in ‘/Users/mariano/PhD/Marea/Fuel/imagenes/’. Implementing #imageDirectory and #baseImageName subclasses can customize that.

Conclusion?   I can take any Pharo image, Gofer MarianoBuilder and just sending #buildFuelImage or #buildXXX I can automatically build my own image with my own tools, settings and customizations. The image will be named and placed exactly where I want.

My final proposal

As said, you can find the code in http://ss3.gemstone.com/ss/MarianoBuilder and the license is MIT. I didn’t call it MarianoBuilder because of ego, but on purpose to make it clear that MarianoBuilder is just for me, it has my own preferences, my own settings, my own projects. What you should copy is the procedure. Copy the idea of using Metacello for something else than managing projects. Create your own ConfigurationOfYou and YourBuilder. Of course, you are very welcome to take a look to MarianoBuilder to get an idea of how to set certain preferences or settings. You are invited to take it as a base and fork it.

There are more things I would like to tell about this topic but the post is already too long so I will continue after…


My small talks at Smalltalks 2011

Smalltalks 2011 was, as usual, a very nice conference. I am glad I could attend even when living in France. This time I gave 2 talks as I mentioned in a previous post.

The talk “Building your own Pharo images with Metacello” was good or at least that’s what I think. Of course, it was a talk that only makes sense for certain people or scenarios. Moreover, it was a “pre-requirement” to know Metacello which n is something not all people know. The talk was in the big auditorium and there were quite a lot of people. The only thing I regret from the presentation is that I forgot to say that the code was MIT and that everybody could take it and adapt it to their own needs. Nevertheless, I added a slide with this information to the final version of the slides (which will be published in the website).

You can find the slides here but notice that most of the presentation was a live demo. You will need to wait for the video if you want to see it 😉  (it was recorded so it should be online soon). I like the topic of this talk so I will try to do a special post about it in the future.

The second talk was the presentation of my paper: “Problems and Challenges when Building an Unused Object Manager for Pharo”. It was in the secondary room so there were a few people (no more than 20). Besides, the talk was in parallel with a nice talk of Hernán Wilkinson. I hope that I least I could explain more or less what I am trying to do for my PhD. The slides of the talk are here.

That’s all folks 🙂


Migrating projects to SqueakSource3

Hi guys. I am one of the guys who is always criticizing www.squeaksource.com because it is down all the time. And when it is not down it is loosing versions. So it is not fair that I continue doing so if there is a new already working solution out there: SqueakSource3 (http://ss3.gemstone.com/ss).

During Smalltalks 2011 I talked to Dale Henrichs who told me that SqueakSource3 was quite stable and has daily backups. SqueakSource3 is a new implementation of SqueakSource but based in Seaside3, Magritte2, etc. Even more (and this is very cool), it is deployed in a GemStone server. Thanks a lot for GemStone for hosting such a service and to all the developers behind SS3.

So, I decided to give it a try. I have started to migrate all my projects or the projects I contribute and I thought I could share that with you.

Migrating projects to SqueakSource3

There are two ways I found in order to migrate packages from one repository to another one. As an example, I will show you how I have migrated Fuel code from http://www.squeaksource.com/Fuel to http://ss3.gemstone.com/ss/Fuel

Pre-optional step

As explained later, you will need to fetch all versions of the packages you want to migrate. Downloading that from squeaksource can be quite slow and you may need a good internet connection. However, if you want to migrate a project you have been development, it is probable that some .mcz are still somewhere in your machine. What you can do is to copy all .mcz files of your machine to the package-cache so that you can get it from there and avoid the network traffic. To do that I often use this bash script:

#!/bin/bash

find /Users/mariano/ -name "*.mcz" -print0 | xargs -0 -I {} cp {} /Users/mariano/Pharo/YOUR-PACKAGE-CACHE/

Using Gofer #fetch and #push

As you know, Gofer is a nice scripting library for Monticello and it provides the methods #fetch (which downloads versions from remote repositories into the local cache) and #push (which uploads local versions from local cache into remote repositories). So the idea is that you can fetch the versions from the original repository and push in the new one. In the example of Fuel, I should do:

Gofer it
squeaksource: 'Fuel';
package: 'Fuel';
package: 'FuelTests';
fetch.

Gofer it
url: 'http://ss3.gemstone.com/ss/Fuel';
package: 'Fuel';
package: 'FuelTests';
push.

Notice that such code could take a lot of time since EACH version of EACH package has to be fetched and pushed. So…let your machine, take a coffee and then come back. In this example, I only migrate two packages (‘Fuel’ and ‘FuelTests’) but there are much more packages in the Fuel repository. Having to write 20 lines of #package: can be a lot. So if you are a lazy guy like me, you can do the following hack:

| packagesNames gofer |

packagesNames := (Gofer new
disablePackageCache;
squeaksource: 'Fuel';
allResolved)
collect: [ :each | each packageName ] as: Set.

gofer := Gofer it
squeaksource: 'Fuel'.

packagesNames do: [:each | gofer package: each].
gofer fetch.

gofer := Gofer it
url: 'http://ss3.gemstone.com/ss/Fuel'.

packagesNames do: [:each | gofer package: each].
gofer push.

That way you can fetch and push all packages. Of course, you can always get the list first, remove by hand the packages that you don’t want to migrate, and finally just migrate the ones you want.

Using Gofer and Metacello configurations

Instead of manually choosing which packages to migrate, if you do have Metacello configurations, why not to directly use them? Dale has an excellent post explaining exactly how to do that. Please read it if you are interested in such approach. Basically it consist of migrating only those packages of a Metacello version. Example:

| gofer |
"Identify the source repository"
gofer := Gofer new squeaksource: 'Fuel';
package: 'ConfigurationOfFuel' yourself.
"Traverse all packages defined in baseline '1.7-baseline' of the Fuel configuration"
(ConfigurationOfFuel  project version:  '1.7-baseline') packages do:[:spec |
"Use the #name and #package: messages and Gofer will fetch
all versions of the Monticello package"
gofer package: spec name ].
"Initiate the download with the #fetch command"
gofer fetch.

"Identify the target repository"
gofer := Gofer new url: 'http://ss3.gemstone.com/ss/Fuel';
package: 'ConfigurationOfFuel' yourself.
"Use the same algorithm for identifying the packages to be pushed"
(ConfigurationOfFuel project version: '1.7-baseline') packages do:[:spec |
gofer package: spec name ].
"Initiate the upload with the #push command"
gofer push.

The only difference with the previous approach is that this way we automatically migrate the packages referenced from the configuration.

Problems I found

Fetching and pushing take a long time, so be patient and try to be with a good internet connection. In my case, I have several errors which I have to deal with:

  •  Timeouts: If you get a “ConnectionTimedOut: Data receive timed out.” then it is clear there was a timeout with a certain package. What I did when I had this error is to open the debugger, go down in the stack a little while up to the place where I see it was doing the load of the version, and do a restart. Otherwise, you can always close the debugger and execute the code again, but this will take more time.
  • If you get the “Error: file is too short” then it means that there is some package (.mcz file) in your package-cache with zero bytes. Open the debugger, go down in the stack and identify which package/version has the problem. Then just go the package cache and remove such file. Then restart the migration procedure.

So, that’s all. I hope I could make your migration easier 🙂