Friday, 25 November 2011

Organising Ivy repos

Edit: since I migrated most of my projects to maven this is less relevant to what I do now.

This is about a trick I use to organise my open source projects.
Unlike in-house projects, open source projects have to allow anyone to download them and build them so they cannot, for example, be dependent on some local library to resolve dependencies.
I use Apache Ivy as my dependency manager and ivyroundup as my public repository. So when my project's ivy configuration needs to resolve, say, slf4j, it can find it and download it automatically. I don't need to keep all the jar files in my project itself, which means I don't need to maintain them etc. So this is good.
If I only had one project we could stop there, but I have several and some are dependent on others. So I might make a change to madura-date-time which is dependent on maduraconfiguration. In the process I might identify a change to maduraconfiguration I need to make. So I do that, publish maduraconfiguration to ivyroundup, then go make my change to madura-date-time and... find I need to make another change to maduraconfiguration. Oops.
Clearly I need a more efficient way to do this and I have one, but before we go there we need to understand that these projects are all in Eclipse, and that means they end up having their dependencies resolved two different ways.
For the official build I use Apache Ant. There is a build.xml file which resolves dependencies, compiles everything, runs the unit tests, packages it into a jar file and even uploads it to Google. It also generates the required configuration files for ivyroundup. You don't need Eclipse to run this, just a Java JDK and Ant.
But for moment by moment development Eclipse runs compiles and, when necessary, resolves dependencies using the same ivy.xml and ivysettings files that Ant uses. But how it finds the repository is a subtly different.
The ivysettings file is an xml file that tells Ivy how to find the repository. This is what mine looks like:
<ivysettings>
    <property name="ivy.cache.dir" value="${user.home}/.ivy2" />
    <property name="roundup-repository" value="http://ivyroundup.googlecode.com/svn/trunk" override="false" />

    <settings  
            defaultResolver="libraries"           
            defaultConflictManager="all" >

    </settings>
    <caches
        checkUpToDate="false"
        defaultCacheDir="${ivy.cache.dir}/cache" />

    <namespaces>
        <namespace name="maven2">
        </namespace>
    </namespaces>

    <resolvers>
        <chain name="libraries">
            <packager name="roundup" buildRoot="${user.home}/.ivy2/packager/build" resourceCache="${user.home}/.ivy2/packager/cache">
                <ivy pattern="${roundup-repository}/repo/modules/[organisation]/[module]/[revision]/ivy.xml"/>
                <artifact pattern="${roundup-repository}/repo/modules/[organisation]/[module]/[revision]/packager.xml"/>
            </packager>
        </chain>
    </resolvers>
</ivysettings>
The resolvers specify where the repository is. You can have more than one but I only need one just now. It uses a property called "roundup-repository" which is defined in the third line and, of course, it points to ivyroundup.
Now comes the tricky part. I want to point to a local repository instead of ivyroundup but I want nothing in the project that I commit (and which others would download) to see that repository. I just know that if it is something I have to edit out before I commit I will forget.
When building under Ant this is easy. I can just define an Ant runtime property in Eclipse that overrides "roundup-repository" so if I launch the build from Eclipse the override value will be used, ie my local repo. Since I define this value as part of the workspace configuration there are no files to accidentally commit because there is nothing in the project. It also means anyone downloading the project doesn't have to set that up.
But when the IvyDE plugin runs it does not see the Ant properties because it isn't Ant (fair enough). There are two ways to override the property. I can define project level properties or workspace level properties. Project level properties will mean I have a file in the project which I have to edit before I commit. So I reject that approach. Workspace level properties are only available if I have a workspace level ivysettings file. But I don't want to do that because that means anyone downloading the project will need to know how to set that up because, of course, it isn't committed.
There is one other way and that is the trick.
I start Eclipse with this in the command line:

-Droundup-repository=file:///home/roger/madura3/ivyroundup-trunk

which points to where my local repo lives. Note that this has to be on the command line after the -vmargs option.
With that in place IvyDE will use my local repo instead of the remote one.
And there is nothing in my project that specifies this so nothing to remember to change when I commit.
What about Ant? Is this enough to tell Ant where to find the repo as well?
Sadly no. I still need an Ant property defining the value for roundup-repository or it breaks. But actually I need a few other Ant properties anyway and I have them in an external file.
Why do I add the symbol to the command line and not to the eclipse.ini file? Well, that is because I run a number of workspaces all of which launch the same Eclipse and hence use the same ini file. But only one of my workspaces needs the roundup-repository defined in this way. Others need other stuff. So the setting does not belong in the ini file.
So, to recap, I have a workspace that uses a local ivy repo without any of the projects in the workspace knowing its location. They only thing they know about is the remote repo, which is all I want people who download it to know about because that is the repo they can access.

Thursday, 10 November 2011

Fricken' Laser!

I decided to make a ray gun. But it had to actually be a ray gun, not something that looks like a ray gun but doesn't do anything. Given the only technology we actually have today that come close to science fiction ray guns is a laser it had to be a laser. I started with this image:
That's a Derringer pistol, a tiny gun produced in the 19th century and favoured by ladies and gamblers for its small size, making it easy to hide. It fired just two shots and I gather it was not too reliable, but I guess waving it about in the right circumstances would be enough. This is way more ornate than I can manage and it isn't a laser, of course. So this is what I made:
And yes, it is a real laser. Lasers are remarkably easy to get hold of these days which should not be a surprise because they are in our mice, in our DVD players and probably a ton of other places. They are quite cheap too. The trigger is a little push-button and the laser itself is the bit poking out the end of the main barrel. It is fairly powerful but I don't think it would pop a balloon. Think laser pointer rather than death ray. Still it does make it a real ray gun.

Just the laser itself was not enough so I added a little peizo oscillator (the black bit on the top and inside the handle is a Teensy which drives it to make an interesting noise when the laser lights up. There is a battery in the handle as well. It is about 5 inches long (similar enough to the Derringer) and should fir discretely into a pocket or a purse. Mrs gets to wield this thing (I have the vortex manipulator).

Programming the Teensy to drive the oscillator was interesting. The oscillator is a very simple thing, it can only play one note at a time, no chords. But I can send any note by frequency and control the timing etc. I can make it play a tune if I want, in this case it make a buzzy sort of noise which seems appropriate.