|Version 3 (modified by duncan, 5 years ago)|
RubyGems is a similar system for Ruby as Cabal + HackageDB + cabal-install is for Haskell.
This is a comparison of the two systems with the aim of finding what lessons we can learn from RubyGems.
Gems are like Cabal packages. There is a .gemspec file which corresponds to a .cabal file. A .gemspec file is actually Ruby source rather than a custom format, however it defines only a piece of structured data, not code. It is a collection of package metadata. A .gemspec file lives in the source directory of the project and can be built into a .gem file for distribution.
".gem packages are a .tar file with a .tar.gz of contents and a .gz of metadata. The metadata is a Gem::Specification in YAML format The only place you see .rb Gem::Specification files is in the local repo and sometimes in the source" -- Eric Hodel
Unlike Cabal packages, Gems require a certain directory layout. Cabal packages mostly follow the autoconf style, allowing different kinds of files to be put in various places, with one set of defaults for Unix (again like the autoconf defaults) and another set of defaults for Windows. Apparently this makes gems hard to package in traditional package managers.
The RubyGems website homepage is fairly nice. It has links to the user guide, the gems command reference, an FAQ and the packaging specification for package authors. Compare this with the Cabal website, or the HackageDB home page, or the Hackage trac homepage. It has been pointed out that the HaskageDB home page needs to be re-written with the new user base in mind.
RubyForge? provides project hosting and distribution for gems. So it's best compared to HackageDB and code.haskell.org.
RubyForge? is not the only gems server. It is possible to run one's own gems server. While it's possible to run a HackageDB server we have not made it especially easy to do so yet. It looks like a gems server is just an http server with a directory of gems files and an index file. This sounds very much like the HackageDB archive format with it's index of .cabal files.
This is rather similar to cabal-install. It is a command line tool to manage the installation of gems.
Note that gem is more of a package manager than cabal-install is at the moment. In particular it tracks the files that it installs and supports uninstallation. It also supports signing of packages. It has a configuration file to record user preferences like always building documentation or running unit tests.
It supports local gems and remote package repositories. A local gem is just a .gem file in the cirrent directory or a gem named on the command line. By default it looks for local gems first and then remote ones. It prompts interactively to ask if dependent gems should be downloaded and installed.
It provides the following commands:
- gem build -- Build a gem file from a specification
- gem cert -- Support signing and managing signed gems
- gem check -- Check installed gems for problems
- gem cleanup -- Cleanup old versions in the repository
- gem contents -- Display the files contained in an installed gem
- gem dependency -- List the dependencies of a gem
- gem environment -- Display information about the gem environment
- gem help -- Provide help about gem commands
- gem install -- Installing a gem
- gem list -- List gems starting with a string
- gem query -- Query for a list of gems
- gem rdoc -- Generate the RDoc files for an installed gem
- gem search -- List gems containing a string
- gem specification -- Extract the Gem::Specification from a gem file
- gem uninstall -- Uninstalling a gem
- gem unpack -- Unpack an installed gem to the current directory
- gem update -- Update your installed gems
Version numbers are just like Cabal version numbers. Package names, versions and version range dependencies are very similar between Cabal and gems. Version constraints can be specified with the usual equality and comparison operators.
There is a versioning policy. It is not enforced though it is recommended. There is a special version dependency construct to support it. Like the proposed Cabal package versioning policy, it is based on the idea that the version number tells us something about the API compatability. If we have tested with package foo-2.2.0, we could use an "optimistic" version dependency of foo >= 2.2.0, or we could use a "pessimestic" dependency of foo >= 2.2.0 && < 2.3. Gems allows the latter to be written as foo ~~> 2.2. Something similar has been posposed for Cabal, with the syntax foo == 2.2.*.