Hermetic - still Amp under the hood

  • Homepage: TBA
  • IRC: try my in ##copyfree on freenode
  • Mercurial:
  • Author: Michael Edgar, Ari Brown, and now Chad Perrin
  • Copyright: 2009-2010
  • License: GPLv2 (inherited from Mercurial -- in transition)


A ruby interface to Mercurial repositories, from the command line or a program.


  • Supports Mercurial repositories completely!
  • Extremely flexible command system.
  • Ampfiles allow easy command creation/modification.
  • Customizable workflows allow multiple command interfaces to the same operations

Known Issues:

  • It lacks Microsoft Windows support.
  • Importing git patches is untested and likely won't run.
  • Creating bundles (the bundle command) likely fails.
  • Specifying files for diffs has no effect.
  • The ability to use -m for commit messages has evaporated for the moment.


% hm add file.txt
% hm commit -m "updated the file"
% hm push

Nothing really changes from using the hg command. There are a few differences here and there (see hm help [COMMAND]), but really, it's pretty much the same.

Right now, we're trying to simplify the docs, to make it easier to tell what things are relevant to someone working with Amp. Most of our documentation is on our website, but here's an example of some Ampfile code:

command "stats" do |c|
  c.workflow :hg
  c.desc "Prints how many commits each user has contributed"
  c.on_run do |opts, args|
    repo = opts[:repository]
    users = {|h, k| h[k] = 0}
    repo.each do |changeset|
      users[changeset.user.split("@").first] += 1
    users.to_a.sort {|a,b| b[1] <=> a[1]}.each do |u,c|
      puts "#{u}: #{c}"

In the on_run handler, repo is a LocalRepository object. Its #each method iterates over ChangeSet objects, which store information about that particular commit, including which user committed it. These objects will be most relevant to users, but we'll try to make things more obvious as we refine our documentation. At the very least, we've tried to provide a useful description of every method we can.


% hm add file.txt
% hm commit -m "leethaxness"
% hm push

Nothing really changes from using the hg/git command. There are a few differences here and there (see hm help [COMMAND]), but really, it's pretty much the same.

Using hm as a library:

require 'amp'           # transition obviously not complete yet
include Amp

repo = Repositories::pick "/Users/ari/src/amp.code"
remote = Repositories::pick ""

make a file...

Dir.chdir "/Users/ari/src/amp.code/"
open "test.txt", "w" {|f| f.puts "hello, world!" }

and add it to the repo!

repo.add "test.txt"


repo.commit :message => 'blah'

do some more things, pull and update...

result = repo.pull remote
result = repo.update if result.success?

(puts "You need to fix things!"; new_irb_session binding) unless result.success?
# type result[:unresolved] to get a list of conflicts

and push!

repo.push remote

Everything here is really straight forward. Plus, if it's not, we've taken the liberty to document as much as possible.


  • Ruby
  • Trollop (should install automatically)
  • Yard (should not install automatically)
  • maybe something I've forgotten


  1. clone repository
  2. gem build hermetic.gemspec
  3. gem install hermetic-0.1.gem


Licensing is a mess. Efforts are being made to transition to the Simplified BSD License. See the LICENSE file.