I've shaved two yaks this weekend:
Ported the NPackage
installcommand to F#. There shouldn't be any visible change in the application: rather, F# lets me write more succinct code for handling HTTP and package dependencies. (Specifically, I was able to replace a lot of my boilerplace C# code with a computation workflow that takes care of deciding which files need to be downloaded again and which ones can be left alone.)
Set up an instance of TeamCity to take the source code from GitHub and build binaries for me. This isn't a version 1.0 release yet, but you're welcome to download the binaries and help me test them.
PS last week I promised I'd implement package dependencies. I haven't done that yet.
PPS here's another .NET packaging system to look out for: Sebastien Lambla's OpenWrap
I implemented the local package database idea that I mentioned last weekend. Now the NPackage client downloads a packages.js file that describes every version of every package; now you don't have to specify full package file URLs with version numbers. I've also switched to JSON syntax for the package files, instead of using my hand-made Yaml-ish parser.
I want to do at least two more things before putting togther an NPackage version 1.0 release:
- Packages should be able to depend on other packages. These dependencies should consist of a package name and, optionally, the range of version numbers that are acceptable. NPackage will pick the latest version of each package that satisfies all the version number constraints.
- Developers should be able to set up a local package repository that takes prececdence over the web site
Hopefully I'll at least have dependencies working by next weekend.
This weekend I've had a couple of productive sessions on NPackage and I'm pretty happy with how it's working out.
I've set up package files on Amazon S3 for the following libraries:
These six packages test a few different scenarios:
- NUnit and SharpZipLib are needed to build NPackage itself
- Rhino Mocks is a good test because the download URL doesn't resemble the name of the file that gets downloaded; I had to write code to parse the HTTP Content-Disposition header to make sense of it
- Cecil is an example of a library that's distributed with the rest of Mono, which is supplied as a large .tar.gz archive (the other libraries on the list above are all .zip files)
- NHibernate is an example of a library that has its own dependencies, i.e. log4net
Although NPackage is working nicely for its own development, I need to put in more work before the installation process is simple enough. Right now the command to install NPackage's own dependencies looks like this:
NPackage http://np.partario.com/nunit-18.104.22.16812/nunit.np \ http://np.partario.com/sharpziplib-0.85.5/sharpziplib.np
I'd like to simplify it to this:
np install nunit sharpziplib
To do this I'll need to handle dependencies properly. I expect I'll need to drop the approach of putting package descriptions in their own files: the client will need to contain enough intelligence to put together a dependency graph and install the right versions of the right packages. It will be easier to do this if the client can download a central package database list and make its decisions based on the descriptions within there.
I envisage having local databases that can contain a few local packages and delegate the rest to the central list on the web. I'd also like the client to be self-contained enough to carry on working even if this central package server falls over: the client should cache the most recent version of the list and work from there.